并查集问题
1主要操作编辑
初始化
查找
合并
2描述编辑
3Input编辑
4Output编辑
#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>using namespace std;int father[50002],a,b,m,n,p;int find(int x){ if (father[x]!=x) father[x]=find(father[x]); return father[x];}int main(){ scanf("%d%d%d",&n,&m,&p); for (int i=1;i<=n;i++) father[i]=i; for (int i=1;i<=m;i++){ scanf("%d%d",&a,&b); a=find(a),b=find(b);father[a]=b; } for(int i=1;i<=p;i++){ scanf("%d%d",&a,&b); a=find(a);b=find(b); if(a==b)printf("Yes");else printf("No"); } return 0;}#include<iostream>
#define MAXN 50010
using namespace std;
int father[MAXN];
int find(int x)
{
return x==father[x]?x:(find(father[x]));
}
int main()
{
int n,kase=0;
long long m;
while(cin>>n>>m &&(n||m))
{
for(int i=1;i<=n;i++)
{
father[i]=i;
}
for(int i=0;i<m;i++)
{
int a,b,c,d;
cin>>a>>b;
c=find(a);
d=find(b);
if (c != d) father[c]=d;
}
int cnt=0;
for(int i=1;i<=n;i++)
{
if(father[i]==i) cnt++;
}
cout<<"Case "<<++kase<< ": " << cnt << endl;
}
return 0;
}
POJ 2492并查集问题(稍微加深版)
#include<iostream>
using namespace std;
const int Max = 2005;
int n, m;
int parent[Max], opp[Max];
void make_set()
{
for(int x = 1; x <= n; x ++)
{
parent[x] = x;
opp[x] = 0;
}
}
int find_set(int x)
{
if(x != parent[x]) parent[x] = find_set(parent[x]);
return parent[x];
}
void union_set(int x, int y)
{
//cout<<"这是第M=="<<M<<"次操作,合并x和y,x=="<<x<<"y=="<<y;
x = find_set(x);
y = find_set(y);
//cout<<"他们的祖先为"<<x<<" "<<y<<endl;
if(x == y)
return;
parent[y] = x;
}
int main()
{
int t, i, x, y;
scanf("%d", &t);
for(i = 1; i <= t; i ++)
{
scanf("%d %d", &n, &m);
make_set();
bool flag = false;
while(m--)
{
scanf("%d %d", &x, &y);
if(flag)
continue;
if(find_set(x) == find_set(y))
{ // 若x,y同在一个集合,则证明有同性的可疑。
flag = true;
}
if(opp[x] == 0 && opp[y] == 0)
{
opp[x] = y;//表明y是x的异性
opp[y] = x;
}
else if(opp[x] == 0)
{
opp[x] = y;
union_set(x, opp[y]);
}
else if(opp[y] == 0)
{
opp[y] = x;
union_set(y, opp[x]);
}
else
{
union_set(x, opp[y]);
union_set(y, opp[x]);
}
}
printf("Scenario #%d:\n", i);
if(flag)
printf("Suspicious bugs found!\n\n");
else
printf("No suspicious bugs found!\n\n");
for(i=1;i<=n;i++) cout<<parent[i]<<" ";
}
return 0;
}
POJ 1703 关于并查集的种类记录问题,这种是带权并查集问题 关键在于弄清各个元素与其父节点间的关系,
第一种是已知儿子与父亲间的关系,父亲与祖父间的关系, 求儿子与祖父间的关系;
第二种是已知x与其父亲a间的关系、y与其父亲b间的关系、x与y间的关系;求a与b间的关系;
#include<iostream>
using namespace std;
#define MAXN 10010
int parent[MAXN],rank[MAXN]; //1表示异类关系;0表示同类关系
int find(int x)
{
if(x!=parent[x])
{
int fa=parent[x];
parent[x]=find(parent[x]); //更改祖先节点
rank[x]=(rank[x]+rank[fa])%2; //更改节点所属类别,节点与祖先的关系,
} // 已知儿子与父亲的关系,父亲与祖父的关系,要求儿子与祖父的关系(只有两类关系)
return parent[x];
}
void UnionSet(int x,int y)
{
int a,b;
a=find(x);
b=find(y);
if(a==b) return ;
parent[a]=b;
rank[a]=(rank[x]+rank[y]+1)%2;
}
//此处最为关键的就是求rank[a],即x的父亲a与b间的关系
//已知条件有一:x与y异类(即为1);二:x与a的关系rank[x];三:y与b的关系rank[y];
//而关系就两种,所以a与b间的关系即为上式
int main()
{
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)
{
parent[i]=i; //记录其父节点
rank[i]=0; //记录该节点的类别
}
while(m--)
{
int a,b;
char ch;
cin>>ch>>a>>b;
if(ch=='D') UnionSet(a,b);
else
{
if(find(a)==find(b))
{
if(rank[a]==rank[b]) cout<<"In the same gang."<<endl;
else cout<<"In different gangs."<<endl;
}
else
cout<<"Not sure yet."<<endl;
}
}
}
return 0;
}
浙公网安备 33010602011771号