zoukankan      html  css  js  c++  java
  • 并查集

    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
  • 相关阅读:
    【BZOJ2138】stone
    【ARC076F】 Exhausted
    [SDOI2018]战略游戏
    CF536D Tavas in Kansas
    [JSOI2018]战争
    ###学习《C++ Primer》- 5
    ###学习《C++ Primer》- 4
    ###Linux基础
    ###Linux基础
    ###Linux基础
  • 原文地址:https://www.cnblogs.com/yijiull/p/7264308.html
Copyright © 2011-2022 走看看