【luogu1330】封锁阳光大学(并查集)

来源:互联网 发布:云主机绑定域名 编辑:程序博客网 时间:2024/05/20 09:47

题目:

我是超链接

题解:

f[i]表示要被染为同色的点,e[i]表示要被染为异色的点,每次合并另一个点的异色点,最后每两组异色点数最小值相加

p[i]表示这一组中同一颜色点的个数

代码:

#include <cstdio>#include <iostream>#include <cstring>#define N 100000*2+5#define D 10000+5using namespace std;int f[D],p[D],e[D],b[D],tot,p1,p2;bool fff=true;int find(int x){if (f[x]!=x) f[x]=find(f[x]);return f[x];}void uni(int x,int y){int a=find(x),b=find(y);if (a==b) return;f[a]=b; p[b]+=p[a];}int main(){int n,m,i,ans=0;scanf("%d%d",&n,&m);for (i=1;i<=n;i++) f[i]=i,p[i]=1;for (i=1;i<=m;i++){int a,b;scanf("%d%d",&a,&b);if (find(a)==find(b)){printf("Impossible"); return 0;}if (e[b]) uni(a,e[b]);if (e[a]) uni(e[a],b);e[a]=f[b]; e[b]=f[a];}for (i=1;i<=n;i++)  if (!b[find(i)])//染一组色   {b[f[i]]=1;  b[find(e[i])]=1;  ans+=min(p[f[i]],p[f[e[i]]]);}//求和  printf("%d",ans);}