P1330 封锁阳光大学 - 二分图染色
传送门
根据题意可知二分图染色。若无法被染成二分图,输出Impossible;反之,对于每个二分图,记录两种颜色的点的个数,取min后记录答案中。
注意,图可能不连通。因此对于每个二分图,都要进行取min操作,而不是对整个图染色后取min。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; inline void r(int &x){ x=0; char ch=getchar(); bool f=0; while(!isdigit(ch)) f=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); if(f) x=-x; } const int N=10000+100,M=100000+100; struct node{ int to,nxt; }e[M<<1]; int head[N],tot; inline void add(int u,int v){ e[++tot]=(node){v,head[u]}; head[u]=tot; } int col[N],colv[4]; bool dfs(int u,int c){ col[u]=c;colv[c]++; for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(col[v]==col[u]) return false; if(!col[v]){ if(!dfs(v,3-c)) return false; } } return true; } int main(){ int n,m; r(n);r(m); for(int i=1;i<=m;i++){ int u,v; r(u);r(v); add(u,v);add(v,u); } int ans=0; for(int i=1;i<=n;i++){ if(!col[i]) { colv[1]=colv[2]=0; if(!dfs(i,1)){ printf("Impossible");return 0; } else ans+=min(colv[1],colv[2]); } } //对于每个联通块分别处理 !!! printf("%d",ans); return 0; } /* 6 6 1 2 2 3 4 3 5 4 5 6 1 6 */