题目: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; }