[并查集]团伙

题号:ZHOJ1258

思路:并查集。

给每个人建立一个“正集”(朋友)、一个“反集”(敌人),反集要么为空、要么指向一个正集,维护这两类集合,最后统计“正集”的个数。

 1 #include<cstdio>
 2 #include<cstring>
 3 const int N=1000;
 4 int ans;
 5 class UnionFindSet {
 6     private:
 7         int anc[N],anti[N];
 8     public:
 9         UnionFindSet(int n) {
10             for(int i=0;i<=n;i++) {
11                 anc[i]=i;
12                 anti[i]=0;
13             }
14         }
15         int Find(int x) {
16             return (x==anc[x])?x:(anc[x]=Find(anc[x]));
17         }
18         void Union(int op,int x,int y) {
19             if(op==1) {
20                 if(Find(y)==Find(x)) return;
21                 anc[Find(y)]=Find(x);
22             }
23             if(op==2) {
24                 if(anti[x]) Union(1,anti[x],y);
25                 if(anti[y]) Union(1,anti[y],x);
26                 if(!anti[x]) anti[x]=Find(y);
27                 if(!anti[y]) anti[y]=Find(x);
28             }
29         }
30         int Count(int n) {
31             bool vis[n+1];
32             memset(vis,0,sizeof vis);
33             for(int i=1;i<=n;i++) vis[Find(i)]=true;
34             int ans=0;
35             for(int i=1;i<=n;i++) if(vis[i]) ans++;
36             return ans;
37         }
38 };
39 int main() {
40     int n,m;
41     scanf("%d%d",&n,&m);
42     UnionFindSet s(n);
43     while(m--) {
44         int op,x,y;
45         scanf("%d%d%d",&op,&x,&y);
46         s.Union(op,x,y);
47     }
48     printf("%d\n",s.Count(n));
49     return 0;
50 }

 

posted @ 2017-06-06 13:15  skylee03  阅读(160)  评论(0编辑  收藏  举报