zoukankan      html  css  js  c++  java
  • 并查集练习2(带权并查集)

    明天旅游去爬山逛庙玩,今天练一天然后早早睡觉啦~024E5D86

    poj1703 Find them, Catch them (带权并查集)

     1 #include<cstdio>
     2 const int N=1e5+1;
     3 int f[N];
     4 int r[N];//表示与父节点的关系,0同类,1不同类
     5 int n;
     6 void init(){
     7     for(int i=1;i<=n;++i){
     8         f[i]=i; r[i]=0;
     9     }
    10 }
    11 int fin(int x){
    12     int t;
    13     if(x==f[x])return x;
    14     t=f[x];//记录父节点
    15     f[x]=fin(f[x]);
    16     r[x]^=r[t];//类别偏移,或r[x]=(r[x]+r[t])%2
    17     return f[x];
    18 }
    19 void uni(int x,int y){
    20     int fx=fin(x);
    21     int fy=fin(y);
    22     f[fx]=fy;
    23     r[fx]=~(r[x]^r[y]);//类别偏移,或r[fx]=(-r[x]+1+r[y]+2)%2
    24                         //  关系:fx与fy= fx与x+ x与y + y与fy
    25 }
    26 int main(){
    27     int t,m,a,b;
    28     char s[3];
    29     scanf("%d",&t);
    30     while(t--){
    31         scanf("%d%d",&n,&m);
    32         init();
    33         while(m--){
    34             scanf("%s%d%d",s,&a,&b);
    35             if(s[0]=='D') uni(a,b);
    36             else{
    37                 if(fin(a)!=fin(b)){
    38                     if(n==2) printf("In different gangs.
    ");
    39                     else printf("Not sure yet.
    ");
    40                 }
    41                 else{
    42                     if(r[a]==r[b])
    43                         printf("In the same gang.
    ");
    44                     else printf("In different gangs.
    ");
    45                 }
    46             }
    47         }
    48     }
    49     return 0;
    50 }
    View Code

    poj2492 A Bug's Life(带权并查集):与上题差不多嗷。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int N=2001;
     5 int f[N];
     6 int r[N];
     7 int n;
     8 void init(){
     9     for(int i=1;i<=n;++i){
    10         f[i]=i; r[i]=0;
    11     }
    12 }
    13 int fin(int x){
    14     int t;
    15     if(x==f[x])return x;
    16     t=f[x];
    17     f[x]=fin(f[x]);
    18     r[x]^=r[t];
    19     return f[x];
    20 }
    21 void uni(int x,int y){
    22     int fx=fin(x);
    23     int fy=fin(y);
    24     f[fx]=fy;
    25     r[fx]=~(r[x]^r[y]);
    26 }
    27 int main(){
    28     int t,m,a,b,k=1,f;
    29     scanf("%d",&t);
    30     while(t--){
    31         scanf("%d%d",&n,&m);
    32         init();
    33         f=1;
    34         while(m--){
    35             scanf("%d%d",&a,&b);
    36             if(f&&fin(a)==fin(b)&&r[a]==r[b])f=0;
    37             else uni(a,b);
    38         }
    39         printf("Scenario #%d:
    %s
    
    ",k++,f?"No suspicious bugs found!":"Suspicious bugs found!");
    40     }
    41     return 0;
    42 }
    View Code

    poj1988 Cube Stacking (带权并查集):栈顶方块为父节点,r[i]为i到父节点的距离,num[fin(i)]表示包含i的栈的大小,相减即可。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int N=30001;
     5 int f[N],r[N],num[N];
     6 int n;
     7 void init(){
     8     for(int i=1;i<N;++i){
     9         f[i]=i; r[i]=0; num[i]=1;
    10     }
    11 }
    12 int fin(int x){
    13     int t;
    14     if(x!=f[x]){
    15         t=f[x];
    16         f[x]=fin(f[x]);
    17         r[x]+=r[t];
    18     }
    19     return f[x];
    20 }
    21 void uni(int x,int y){
    22     int fx=fin(x);
    23     int fy=fin(y);
    24     if(fx!=fy){
    25         f[fy]=fx;
    26         r[fy]=num[fx];
    27         num[fx]+=num[fy];
    28     }
    29 }
    30 int main(){
    31     int m,a,b;
    32     char s[3];
    33     scanf("%d",&m);
    34     init();
    35     while(m--){
    36         scanf("%s",s);
    37         if(s[0]=='M'){
    38             scanf("%d%d",&a,&b);
    39             uni(a,b);
    40         }
    41         else{
    42             scanf("%d",&a);
    43             printf("%d
    ",num[fin(a)]-r[a]-1);
    44         }
    45     }
    46     return 0;
    47 }
    View Code

    hdu3047 Zjnu Stadium(带权并查集)

     1 #include<cstdio>
     2 #include<map>
     3 using namespace std;
     4 const int N=50001;
     5 int f[N];
     6 int r[N];
     7 int n,cnt;
     8 void init(){
     9     for(int i=1;i<=n;++i){
    10         f[i]=i; r[i]=0;
    11     }
    12 }
    13 int fin(int x){
    14     int t;
    15     if(x!=f[x]){
    16         t=f[x];
    17         f[x]=fin(f[x]);
    18         r[x]+=r[t];
    19     }
    20     return f[x];
    21 }
    22 void uni(int x,int y,int d){
    23     int fx=fin(x);
    24     int fy=fin(y);
    25     if(fx==fy){
    26         if(r[y]-r[x]!=d) cnt++;
    27     }
    28     else{
    29         f[fy]=fx;
    30         r[fy]=-r[y]+r[x]+d;
    31     }
    32 }
    33 int main(){
    34     int m,d,i,a,b;
    35     while(scanf("%d%d",&n,&m)==2){
    36         cnt=0;
    37         init();
    38         while(m--){
    39             scanf("%d%d%d",&a,&b,&d);
    40             uni(a,b,d);
    41         }
    42         printf("%d
    ",cnt);
    43     }
    44     return 0;
    45 }
    View Code

    hdu3038 How Many Answers Are Wrong(带权并查集)与上题差不多耶。

     1 #include<cstdio>
     2 #include<map>
     3 using namespace std;
     4 const int N=200001;
     5 int f[N];
     6 int r[N];//表示与父节点之间的和
     7 int n,cnt;
     8 void init(){
     9     for(int i=0;i<=n;++i){
    10         f[i]=i; r[i]=0;
    11     }
    12 }
    13 int fin(int x){
    14     int t;
    15     if(x!=f[x]){
    16         t=f[x];
    17         f[x]=fin(f[x]);
    18         r[x]+=r[t];
    19     }
    20     return f[x];
    21 }
    22 void uni(int x,int y,int d){
    23     int fx=fin(x);
    24     int fy=fin(y);
    25     if(fx==fy){
    26         if(r[y]-r[x]!=d) cnt++;
    27     }
    28     else{
    29         f[fy]=fx;
    30         r[fy]=-r[y]+r[x]+d;
    31     }
    32 }
    33 int main(){
    34     int m,d,i,a,b;
    35     while(scanf("%d%d",&n,&m)==2){
    36         cnt=0;
    37         init();
    38         while(m--){
    39             scanf("%d%d%d",&a,&b,&d);
    40             uni(a-1,b,d);
    41         }
    42         printf("%d
    ",cnt);
    43     }
    44     return 0;
    45 }
    View Code

    poj1182 食物链 (带权并查集)经典吖orz.

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int N=50001;
     5 int f[N];
     6 int r[N];//表示与父节点的关系,0表示同类,1表示被吃,2表示吃父节点
     7 int n,ans;
     8 void init(){
     9     for(int i=1;i<=n;++i){
    10         f[i]=i; r[i]=0;
    11     }
    12 }
    13 int fin(int x){
    14     int t;
    15     if(x!=f[x]){
    16         t=f[x];
    17         f[x]=fin(f[x]);
    18         r[x]=(r[x]+r[t])%3;
    19     }
    20     return f[x];
    21 }
    22 void uni(int x,int y,int d){
    23     int fx=fin(x);
    24     int fy=fin(y);
    25     if(fx==fy){
    26         if((r[x]-r[y]+3)%3!=d) ans++;
    27     }
    28     else{
    29         f[fx]=fy;
    30         r[fx]=(-r[x]+d+r[y]+3)%3;
    31     }
    32 }
    33 int main(){
    34     int m,a,b,d;
    35     scanf("%d%d",&n,&m);
    36     init();
    37     ans=0;
    38     while(m--){
    39         scanf("%d%d%d",&d,&a,&b);
    40         if(a>n||b>n||(d==2&&a==b))ans++;//假话:a或b都大于n,或a吃a
    41         else  uni(a,b,d-1);
    42     }
    43     printf("%d
    ",ans);
    44     return 0;
    45 }
    View Code

    poj2912 Rochambeau(带权并查集,枚举)石头剪刀布的游戏,并查集部分和上题食物链很像哦。枚举每个小孩为裁判时的情况,再并查集判断。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 const int N=501;
     6 const int M=2001;
     7 int f[N],r[N];
     8 int n;
     9 void init(){
    10     for(int i=0;i<n;++i){
    11         f[i]=i; r[i]=0;
    12     }
    13 }
    14 int fin(int x){
    15     int t;
    16     if(x!=f[x]){
    17         t=f[x];
    18         f[x]=fin(f[x]);
    19         r[x]=(r[x]+r[t])%3;
    20     }
    21     return f[x];
    22 }
    23 int uni(int x,int y,int d){
    24     int fx=fin(x);
    25     int fy=fin(y);
    26     if(fx==fy){
    27         if((r[x]-r[y]+3)%3!=d) return 0;
    28         return 1;
    29     }
    30     else{
    31         f[fx]=fy;
    32         r[fx]=(-r[x]+d+r[y]+3)%3;
    33         return 1;
    34     }
    35 }
    36 int main(){
    37     int m,d,i,j,a[M],b[M],flag,cnt,id,ans,D[M];
    38     char s[M],c;
    39     while(scanf("%d%d",&n,&m)==2){
    40         for(i=1;i<=m;++i){
    41             scanf("%d",&a[i]);
    42             while(scanf("%c",&s[i]),s[i]==' ');
    43             scanf("%d",&b[i]);
    44             if(s[i]=='=')D[i]=0;
    45             else if(s[i]=='>')D[i]=1;
    46             else D[i]=2;
    47         }
    48         cnt=ans=id=0;
    49         for(i=0;i<n;++i){//枚举每个裁判
    50             init();
    51             flag=0;
    52             for(j=1;j<=m;++j){
    53                 if(a[j]!=i&&b[j]!=i){
    54                     if(!uni(a[j],b[j],D[j])){
    55                         flag=1;
    56                         if(j>ans) ans=j;//取最大的矛盾轮数
    57                         break;
    58                     }
    59                 }
    60             }
    61             if(!flag){ id=i; cnt++;}
    62         }
    63         if(cnt==0) puts("Impossible");
    64         else if(cnt==1)
    65             printf("Player %d can be determined to be the judge after %d lines
    ",id,ans);
    66         else  puts("Can not determine");
    67     }
    68     return 0;
    69 }
    View Code

    poj1733 Parity game(带权并查集,离散化)

    题意:有一个已知长度的01串,给出多个区间[l,r],并知道区间中1的个数是奇数还是偶数,问前几个区间互不矛盾。

    离散化hash暂时还不会,先用map映射处理大数据问题吧。。

     1 #include<cstdio>
     2 #include<map>
     3 using namespace std;
     4 const int N=5001;
     5 int f[N];
     6 int r[N];//表示到父节点的1的个数的奇偶性,0表示偶数个1,1表示奇数个1
     7 int n;
     8 void init(){
     9     for(int i=0;i<N;++i){
    10         f[i]=i; r[i]=0;
    11     }
    12 }
    13 int fin(int x){
    14     int t;
    15     if(x!=f[x]){
    16         t=f[x];
    17         f[x]=fin(f[x]);
    18         r[x]=(r[x]+r[t])%2;
    19     }
    20     return f[x];
    21 }
    22 int uni(int x,int y,int d){
    23     int fx=fin(x);
    24     int fy=fin(y);
    25     if(fx==fy){
    26         if((r[x]-r[y]+2)%2!=d) return 0;
    27         return 1;
    28     }
    29     f[fx]=fy;
    30     r[fx]=(-r[x]+d+r[y]+2)%2;
    31     return 1;
    32 }
    33 int main(){
    34     int m,d,i,k,a,b,flag,ans;
    35     char s[10];
    36     while(scanf("%d%d",&n,&m)==2){
    37         init();
    38         map<int,int>p;
    39         flag=1;
    40         k=0;
    41         ans=m;
    42         for(i=0;i<m;++i){
    43             scanf("%d%d%s",&a,&b,s);
    44             if(!flag)continue;
    45             d=(s[0]=='e'?0:1);
    46             b++;
    47             if(p.find(a)==p.end()) p[a]=k++;
    48             if(p.find(b)==p.end()) p[b]=k++;
    49             if(!uni(p[a],p[b],d)){
    50                 flag=0;
    51                 ans=i;
    52             }
    53         }
    54         printf("%d
    ",ans);
    55     }
    56     return 0;
    57 }
    View Code

    写完随笔怎么突然有种很萌比的感觉。。。下个月的今天再复习一下好啦。。

  • 相关阅读:
    Druid初步学习
    跨区域的application共享问题。
    jsp系统时间和时间对比(活动结束不结束)
    Intellij Idea中运行tomcat 报內存溢出
    SpringMVC -rest风格修改删除
    Redis服务器的创建服务
    Double和double的区别
    1.Redis安装(转)
    查看Mysql执行计划
    linux查询日志命令总结
  • 原文地址:https://www.cnblogs.com/GraceSkyer/p/5769014.html
Copyright © 2011-2022 走看看