封锁阳光大学(染色)P1330

题目:https://www.luogu.com.cn/problem/P1330

阳光大学的校园是一张由 n 个点构成的无向图,n 个点之间由 m 条道路连接。每只河蟹可以对一个点进行封锁,当某个点被封锁后,与这个点相连的道路就被封锁了,曹就无法在这些道路上刷街了。非常悲剧的一点是,河蟹是一种不和谐的生物,当两只河蟹封锁了相邻的两个点时,他们会发生冲突。

询问:最少需要多少只河蟹,可以封锁所有道路并且不发生冲突。


①每一条边所连接的点中,至少要有一个被选中

②每一条边所连接的两个点,不能被同时选中。

那我们仔细想一下,我们随便放一个河蟹,相邻的点就不能放。延伸出去,整个图就被确定了。

所以对于一个连通图,要么不可能放置成功,要么有两种放置方法。

为什么有两种放置方法呢?

因为对于一个点有放和不放两种策略。

那我们对每一个子图dfs(因为图可能不连通)

每次统计两种策略的放置数,累加最小值即可。

#include <bits/stdc++.h>
using namespace std;
int n,m,vis[10009];
vector<int>vec[10009];
int color[10009],t,tt;
int z[10009];
void dfs(int now,int se)
{
    for(int i=0;i<vec[now].size();i++)
    {
        int w=vec[now][i];
        if(color[w]==-1)//没搜过
        {
            if(color[now])    color[w]=0;
            else    color[w]=1;//总之颜色不能相同
            cnt[color[w]]++;
            dfs(w);    
        }
        else if(color[w]==color[now])//搜过但相邻点颜色相同
        {
            cout<<"Impossible";
            exit(0);    
        } 
    }
    return min(cnt[0],cnt[1]+1);//起点染色为1,要加上 
} 
int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int l,r;
        cin>>l>>r;
        vec[l].push_back(r);
        vec[r].push_back(l);
    }
    memset(color,-1,sizeof(color));
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        if(vis[i])    continue;
        if(color[i]==-1)//遇到新的子图
        {
            cnt[0]=cnt[1]=0;
            color[i]=1;
            ans+=dfs(i);    
        } 
    }
    cout<<ans;
} 
原文地址:https://www.cnblogs.com/iss-ue/p/12515479.html