并查集

Exclusive-OR

 UVALive - 4487 

 带权并查集,回去再写

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define CLR(m,a) memset(m,a,sizeof(m))
 4 const int maxn=20010;
 5 int f[maxn],d[maxn];
 6 int n,q;
 7 void init(){
 8     for(int i=0;i<=n;i++){
 9         f[i]=i;
10         d[i]=0;
11     }
12 }
13 
14 int gf(int x){
15     if(x!=f[x]){
16         int r=f[x];
17         f[x]=gf(r);
18         d[x]=d[x]^d[r];
19     }
20     return f[x];
21 }
22 int uni(int a,int b,int v){
23     int pa=gf(a);
24     int pb=gf(b);
25     if(pa==pb) return (d[a]^d[b])==v;
26     if(pa==n) swap(pa,pb);
27     f[pa]=pb;
28     d[pa]=d[a]^d[b]^v;
29     return 1;
30 }
31 
32 struct Ask{
33     int p,a;
34     bool operator<(const Ask& x){
35         return p<x.p;
36     }
37 };
38 Ask ask[maxn<<1];
39 int query(int k){
40     for(int i=0;i<k;i++) ask[i].p=gf(ask[i].a);
41     sort(ask,ask+k);
42     int l=0,ans=0;
43     while(l<k){
44         int r=l;
45         while(r+1<k&&ask[r].p==ask[r+1].p) r++;
46         int num=r-l+1;
47         if(ask[l].p!=n&&num&1) return -1;
48         for(int i=l;i<=r;i++) ans^=d[ask[i].a];
49         l=r+1;
50     }
51     return ans;
52 }
53 int main()
54 {
55     int kase=0;
56     char c[5],s[20];
57     while(scanf("%d%d",&n,&q)&&(n||q)){
58         printf("Case %d:
",++kase);
59         int flag=-1;
60         init();
61         int ct=0;
62         for(int u=0;u<q;u++){
63             scanf("%s",c);
64             if(c[0]=='I'){
65                 ct++;
66                 gets(s);
67                 if(flag!=-1) continue;
68                 int p,q,v;
69                 int res;
70                 int t=sscanf(s,"%d%d%d",&p,&q,&v);
71                 if(t==2){
72                     res=uni(p,n,q);
73                 }else{
74                     res=uni(p,q,v);
75                 }
76                 if(!res) flag=ct;
77             }else {
78                 int k;
79                 scanf("%d",&k);
80                 for(int i=0;i<k;i++) {
81                     scanf("%d",&ask[i].a);
82                 }
83                 if(flag!=-1) continue;
84                 int res=query(k);
85                 if(res==-1) puts("I don't know.");
86                 else printf("%d
",res);
87             }
88         }
89         if(flag!=-1) printf("The first %d facts are conflicting.
",flag);
90         puts("");
91     }
92     return 0;
93 }
View Code

Almost Union-Find

 UVA - 11987

题意:要求实现带删除的并查集。

思路就是将要点的影响力减为0。然后开辟新的节点(代码中的id[i]就是这个用处)去合并。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define CLR(m,a) memset(m,a,sizeof(m))
 4 
 5 const int maxn=200010;
 6 
 7 int f[maxn],cnt[maxn],sum[maxn];
 8 int id[maxn]; //本替关键
 9 int n,m;
10 int tot;
11 void init(){
12     for(int i=0;i<=n;i++){
13         f[i]=i;
14         sum[i]=i;
15         cnt[i]=1;
16         id[i]=i;
17     }
18 }
19 
20 int gf(int x){
21     return x==f[x]?f[x]:f[x]=gf(f[x]);
22 }
23 
24 void uni(int a,int b){
25     int pa=gf(a);
26     int pb=gf(b);
27     if(pa!=pb){
28         f[pa]=pb;
29         cnt[pb]+=cnt[pa];
30         sum[pb]+=sum[pa];
31     }
32 }
33 
34 void move(int a){
35     int pa=gf(id[a]);  //
36     sum[pa]-=a;
37     cnt[pa]--;
38     //开辟新的节点
39     id[a]=++tot;
40     f[tot]=tot;
41     sum[tot]=a;
42     cnt[tot]=1;
43 }
44 
45 int main(){
46     while(scanf("%d%d",&n,&m)!=EOF){
47         init();
48         int c,p,q;
49         tot=n;
50         for(int i=0;i<m;i++){
51             scanf("%d",&c);
52             if(c==3){
53                 scanf("%d",&p);
54                 int pf=gf(id[p]);
55                 printf("%d %d
",cnt[pf],sum[pf]);
56             }else{
57                 scanf("%d%d",&p,&q);
58                 if(c==1){
59                     uni(id[p],id[q]);
60                 }else{
61                     int pf=gf(id[p]),qf=gf(id[q]);
62                     if(pf==qf) continue;
63                     move(p);
64                     uni(id[p],id[q]);
65                 }
66             }
67         }
68     }
69     return 0;
70 }
View Code

Junk-Mail Filter

HDU - 2473

题意:并查集的删除.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2e6+10;
 4 int vis[maxn];
 5 int f[maxn],b[maxn];
 6 int cnt=0;
 7 int gf(int x){
 8     return x==f[x]?x:f[x]=gf(f[x]);
 9 }
10 
11 int main(){
12     int n,m;
13   //  freopen("in.txt","r",stdin);
14     int kase=0;
15     while(scanf("%d%d",&n,&m)&&(n||m)){
16     char s[4];
17     int x,y;
18     cnt=n;
19     memset(vis,0,sizeof(vis));
20     for(int i=0;i<=n;i++) {
21         f[i]=i;
22         b[i]=i;
23     }
24     for(int i=0;i<m;i++){
25         scanf("%s",s);
26         if(s[0]=='S'){
27             scanf("%d",&x);
28             b[x]=cnt;
29             f[cnt]=cnt++;
30         }else{
31             scanf("%d%d",&x,&y);
32             int pa=gf(b[x]),pb=gf(b[y]);
33             if(pa!=pb) f[pa]=pb;
34         }
35     }
36     int ans=0;
37     for(int i=0;i<n;i++){
38         int r=gf(b[i]);
39         if(!vis[r]){
40             ans++;
41             vis[r]=1;
42         }
43     }
44     printf("Case #%d: %d
",++kase,ans);
45     }
46 }
View Code

Warfare

HDU - 2904
题意:给n个点,点权为w,相连的边的权值为点权值之和.现在要破坏一些边使得图中不存在环,问最小代价是多少(代价即为破坏边的权值)
比较水~给边排序一下,然后并查集搞
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=110;
 4 
 5 int f[maxn];
 6 struct Edge{
 7     int u,v,w;
 8     bool operator <(const Edge& a)const{
 9         return w>a.w;
10     }
11 }e[maxn*maxn];
12 int w[maxn],g[maxn][maxn];
13 
14 int gf(int x){
15     return x==f[x]?x:f[x]=gf(f[x]);
16 }
17 
18 int main(){
19     int t;
20 //    freopen("in.txt","r",stdin);
21     scanf("%d",&t);
22     while(t--){
23         int n;
24         memset(g,0,sizeof(g));
25         scanf("%d",&n);
26         int u,v,m;
27         for(int i=0;i<n;i++){
28             scanf("%d%d%d",&u,&w[i],&m);
29             for(int j=0;j<m;j++){
30                 scanf("%d",&v);
31                 g[u][v]=g[v][u]=1;
32             }
33         }
34         int cnt=0;
35         int sum=0;
36         for(int i=0;i<n;i++){
37             for(int j=i+1;j<n;j++){
38                 if(g[i][j]){
39                     e[cnt].u=i;
40                     e[cnt].v=j;
41                     e[cnt].w=w[i]+w[j];
42                     sum+=e[cnt].w;
43                     cnt++;
44                 }
45             }
46         }
47         sort(e,e+cnt);
48         for(int i=0;i<n;i++) f[i]=i;
49         int temp=0;
50         for(int i=0;i<cnt;i++){
51             int pa=gf(e[i].u);
52             int pb=gf(e[i].v);
53             if(pa!=pb){
54                 f[pa]=pb;
55                 temp+=e[i].w;
56             }
57         }
58         printf("%d
",sum-temp);
59     }
60     return 0;
61 }
View Code
原文地址:https://www.cnblogs.com/yijiull/p/7264308.html