题目链接:https://www.luogu.org/problem/P1330
题意:一个有n(1000)个点m(10000)条边的无向图,要封锁该图使得每条边都不能用,将一个河蟹部署在点上可使它的相邻边都报废,但相邻的两点不能够同时部署河蟹,求问是否能封锁整个图,如果能的话最少需要多少河蟹
分析:先看不能的情况,画图稍微分析一下就可以发现只要有奇环就无法封锁。
然后因为相邻两点不能同时部署,那我们就可以考虑染色了,且一张图要么不能染(奇环),能染的话肯定也只有两种情况,比较较小的即可,奇环的寻址可以直接在找环时判断,因为偶环的话第一次到达和第二次到达染的色是相同的,而奇环不同
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e4+7; const int N=1e5+7; const ll inf=0x3f3f3f3f; #define mem0(a) memset(a,0,sizeof(a)) int nxt[N]; int head[N]; int to[N]; int cnt; bool used[maxn]; int sum[2]; int col[maxn]; void add(int u,int v){ cnt++; to[cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } bool dfs(int nd,int color){ if(used[nd]){ if(col[nd]==color){ return true; } return false;//其实就是奇环不满足 } used[nd]=true; col[nd]=color; sum[color]++; for(int i=head[nd];i;i=nxt[i]){ if(!dfs(to[i],color^1)) return false;//不能继续染色了 } return true;//说明可以继续染色下去 } int main(){ int n,m;scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int x,y;scanf("%d%d",&x,&y); add(x,y); add(y,x); } int ans=0; for(int i=1;i<=n;i++){ if(used[i])continue;//这个点在之前已经遍历过了 sum[0]=sum[1]=0; if(!dfs(i,0)){ printf("Impossible"); return 0;//直接跳出 } ans+=min(sum[0],sum[1]);//把每个联通子图的最少河蟹数加上 } printf("%d ",ans); return 0; }