并查集 Hdu 1272 (判环)+ Hdu 1213 + Hdu 1232 + Hdu 3172

来源:互联网 发布:教师网络研修注册 编辑:程序博客网 时间:2024/05/29 16:45

Hdu 1272 小希的迷宫

思路:两点的根节点相同,并且他们又彼此连通,则说明构成环。如果无环且 点数-1==边数 则说明只有一个连通块

#include <cstdio>#include <cstring>const int MAX=100005;bool visit[MAX];class Disjoint_Set{public:int father[MAX];            /*father[x]表示x的父节点*/int rank[MAX];              //以该节点为根节点的点数,同时起到按秩合并的作用void Init (int n){for (int i=0;i<=n;i++)Make_Set (i);}void Make_Set (int x){father[x]=x;rank[x]=1;}int Find_Set (int x){if (x != father[x])father[x] = Find_Set(father[x]);//回溯return father[x];}bool Union (int x,int y){//返回false表示要合并的两点已在同一个集合中int a=Find_Set (x);int b=Find_Set (y);if (a == b)return false;if (rank[a] >= rank[b]){father[b]=a;rank[a]+=rank[b];}else{father[a]=b;rank[b]+=rank[a];}return true;}}ob;int main (){int n,m;while (~scanf("%d%d",&n,&m),n!=-1 && m!=-1)    {        if (n==0 && m==0)        {            printf("Yes\n");            continue;        }ob.Init(MAX);memset(visit,false,sizeof(visit));visit[n]=visit[m]=true;ob.Union(n,m);int cnt=1;   //已经有一条边int tmp=2;   //已经有2个点bool flag=true;while(scanf("%d%d",&n,&m),n||m)        {            cnt++;            if (visit[n]==false)            {                visit[n]=true;                tmp++;            }            if (visit[m]==false)            {                visit[m]=true;                tmp++;            }            if (ob.Union(n,m)==false)                flag=false;  //若n和m的根节点相同,并且他们又彼此连通,则说明构成环        }if (flag && cnt==tmp-1) //无环,且所有点连通            printf("Yes\n");        else            printf("No\n");}return 0;}

Hdu 1213 How Many Tables

题意:有n个人参加的party,要准备多少张桌子,使得任意桌子上坐的人都是相互认识的。求最少要准备的桌子的数量。

#include <cstdio>const int MAX=1005;class Disjoint_Set{public:int father[MAX];            /*father[x]表示x的父节点*/int rank[MAX];              //以该节点为根节点的点数,同时起到按秩合并的作用void Init (int n){for (int i=0;i<=n;i++)Make_Set (i);}void Make_Set (int x){father[x]=x;rank[x]=1;}int Find_Set (int x){if (x != father[x])father[x] = Find_Set(father[x]);//回溯return father[x];}void Union (int x,int y){int a=Find_Set (x);int b=Find_Set (y);if (a == b)return;if (rank[a] >= rank[b]){father[b]=a;rank[a]+=rank[b];}else{father[a]=b;rank[b]+=rank[a];}}}ob;int main (){int T,n,m;scanf("%d",&T);while (T--)    {        scanf("%d%d",&n,&m);ob.Init(n);int a,b,ans=0,i;for (i=1;i<=m;i++){scanf("%d%d",&a,&b);            ob.Union(a,b);}for (i=1;i<=n;i++)            if (ob.father[i]==i)                ans++;printf("%d\n",ans);}return 0;}

Hdu 1232 畅通工程

#include <cstdio>const int MAX=1005;class Disjoint_Set{public:int father[MAX];int rank[MAX];              //以该节点为根节点的点数,同时起到按秩合并的作用void Init (int n){for (int i=0;i<=n;i++)Make_Set (i);}void Make_Set (int x){father[x]=x;rank[x]=1;}int Find_Set (int x){if (x != father[x])father[x] = Find_Set(father[x]);//回溯return father[x];}void Union (int x,int y){int a=Find_Set (x);int b=Find_Set (y);if (a == b)return;if (rank[a] >= rank[b]){father[b]=a;rank[a]+=rank[b];}else{father[a]=b;rank[b]+=rank[a];}}}ob;int main (){int n,m;while (~scanf("%d%d",&n,&m),n)       {ob.Init(n);int a,b,ans=0,i;for (i=1;i<=m;i++){scanf("%d%d",&a,&b);            ob.Union(a,b);}for (i=1;i<=n;i++)            if (ob.father[i]==i)                ans++;printf("%d\n",ans-1);}return 0;}

Hdu 3172 Virtual Friends

给出m条交友信息,每一句含两个人名,表示两个人成为朋友,求是这两个人朋友的有多少个人(含自己)

时间卡的比较严,名字不要用STL的string,用map映射时间还是可以接受的

输入格式很坑爹

#include <iostream>#include <cstdio>#include <string>#include <map>using namespace std;const int MAX=100005;class Disjoint_Set{public:int father[MAX];            /*father[x]表示x的父节点*/int rank[MAX];              //以该节点为根节点的点数,同时起到按秩合并的作用void Init (int n){for (int i=0;i<=n;i++)Make_Set (i);}void Make_Set (int x){father[x]=x;rank[x]=1;}int Find_Set (int x){if (x != father[x])father[x] = Find_Set(father[x]);//回溯return father[x];}void Union (int x,int y){int a=Find_Set (x);int b=Find_Set (y);if (a == b)return;if (rank[a] >= rank[b]){father[b]=a;rank[a]+=rank[b];}else{father[a]=b;rank[b]+=rank[a];}}}ob;int main (){int T,n;while (~scanf("%d",&T))while (T--)    {        scanf("%d",&n);ob.Init(MAX);int id=1;char str[25],ch[25];map<string,int> m;for (int i=1;i<=n;i++){scanf("%s%s",str,ch);if (m[str]==0)                m[str]=id++;            if (m[ch]==0)                m[ch]=id++;            int a=m[str];            int b=m[ch];            ob.Union(a,b);            printf("%d\n",ob.rank[ ob.Find_Set(m[str]) ]);}}return 0;}



0 0
原创粉丝点击