题目:https://www.luogu.org/problemnew/show/P1330
可以想到每条边必有一段“封锁”而另一端必不“封锁”。
1.进一步想想,只要确定该边一端的状态,就能确定其另一端的状态,再由另一端影响别的点。
所以同一连通块中必然只有确定的两种方案!
2.且这两种方案中,一种的封锁的点必是另一种的未封锁的点。
所以可以将点染成两种颜色来计数!需要注意的是每次加该连通块中数量少的颜色,不需要不同的连通块之间还保持相同颜色。
而且注意遍历边,而非未染色的点,以防只有自己一个点的连通块。
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std; int n,m,col[10005],ca,cb,s,x,y,xnt,nex[10005]; struct Node{ int next,to,from; }edge[200005]; bool flag; void add(int x,int y) { xnt++; edge[xnt].next=nex[x]; edge[xnt].from=x; edge[xnt].to=y; nex[x]=xnt; } void co(int a) { for(int i=nex[a];i;i=edge[i].next) { int v=edge[i].to; if(col[v]==col[a]) { printf("Impossible"); exit(0); } if(col[v])continue; col[v]=-col[a]; if(col[v]==1)ca++; else cb++; co(v); } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); add(x,y);add(y,x); } for(int i=1;i<=2*m;i++) if(!col[edge[i].from]&&!col[edge[i].to]) { col[edge[i].from]=1; ca=1;cb=0; co(edge[i].from); s+=min(ca,cb); } printf("%d",s); return 0; }