并查集例题 HDU——1272

来源:互联网 发布:淘宝网匹克运动装 编辑:程序博客网 时间:2024/06/08 13:11

并查集主要处理一些不相交集合的合并问题

基本操作:

(1)建立一个新的并查集,其中包含S个元素的集合。

(2)把元素x和元素y所在的集合合并,要求x和y所在的集合不相交。

(3)找到x所在集合的根,该操作可以用于判断两个元素是否位于同一集合。

例题:HDU——1272



<span style="font-size:18px;">#include<stdio.h>#include<string.h>#include<stdlib.h>#include<algorithm>#include<iostream>#include<map>#include<math.h>#include<queue>using namespace std;#define maxn 100010#define INF 0x3f3f3f3fint a,b,x,cnt,k,ok;int p[maxn];//并查集int m[maxn];//标记点是否出现过//把x的父亲节点保存在p[x]中(如果x没有父亲,则p[x]=x)int find(int x)//查找x所在树的根节点{     return x==p[x]?x:p[x]=find(p[x]);//如果p[x]=x,则x本身就是树根,返回x,否则返回x的父亲p[x]所在树的树根}int make(int a,int b)//合并a和b所在的集合{     int x=find(a);     int y=find(b);     if(x<y)     p[x]=y;//把x作为y的儿子,则两个树就合并成一棵树了     else     p[y]=x;}int main(){     while(1)     {          for(int i=0;i<maxn;i++)          {               p[i]=i;//初始化并查集               m[i]=0;//初始化标记数组,所有点都没出现过          }          cnt=0,k=0,ok=1;          while(scanf("%d%d",&a,&b)!=EOF)          {               if(a==0&&b==0||a==-1&&b==-1) break;               if(find(a)!=find(b))//find()找出两个端点所在集合编号               {//如果不在同一集合,合并                    m[a]=1;                    m[b]=1;                    make(a,b);               }               else               {                    ok=0;//两个点存在,同时又在同一个连通分量里,所以这个连通分量存在一个环               }          }          if(a==-1&&b==-1) break;          for(int i=1;i<=100000;i++)          {               if(m[i]&&p[i]==i)//来证明是否只有一个连通分量               {                    cnt++;               }               if(m[i]!=0)//一个数据都没有时输出yes               k++;          }          if(k==0)          printf("Yes\n");          else if(cnt==1&&ok==1)          printf("Yes\n");          else          printf("No\n");     }     return 0;}</span>


0 0
原创粉丝点击