写一道题的缘故整理来的(尽管最后发现并不需要用到并查集)
记得之前整理过一个,估计年纪大了,个人感觉这个更清楚一点(不过之前详解了过程)
用到的是循环路径压缩,详见代码:
#include<iostream>
#include<algorithm>
using namespace std;
int pre[120];
int find(int s)//查找该元素所对的组
{
if(pre[s]==s) return s;
int x=s;
while(s!=pre[s])
s=pre[s];
int tep;
while(x!=pre[x])
{
tep=pre[x];
pre[x]=s;
x=tep;
}
return x;
}
void join(int a,int b)//将两个元素塞入同一组
{
int p=find(a);
int q=find(b);
if(p!=q)
pre[p]=q;
}
bool isconnected(int a,int b)//观察两个元素是否一组
{
if(find(a)==find(b))
return true;
else
return false;
}
int main()
{
int n;cin>>n;//输入人数
for(int i=1;i<=n;i++)
{
pre[i]=i;
}
int m;cin>>m;//输入条件数
for(int i=0;i<m;i++)
{
int x,y;
cin>>x>>y;//输入有关系的两人
if(isconnected(x,y)==true)continue;//判断是否在同一组
else join(x,y);//否则合为一组
}
return 0;
}
牛客补题代码(同为并查集)
#include<iostream>
#include<algorithm>
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 7;
const int mod = 1000000007;
int pre[maxn], sum[maxn];
int find(int x)
{
return (x==pre[x])?x:pre[x]=find(pre[x]);
}
int main()
{
int n,m,t;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
pre[i]=i;
sum[i]=1;
}
string s,last;
int lastnum;
for(int i=0;i<m;i++)
{
cin>>t>>s;
if(s==last)
{
int fx=find(lastnum);
int fy=find(t);
if(fx==fy)continue;
if(fx>fy) swap(fx,fy);
pre[fy]=fx;
sum[fx]+=sum[fy];
}
else
lastnum=t,last=s;
}
for (int i = 1; i <= n; ++i) {
if (i > 1) cout << " ";
cout << sum[find(i)] - 1;
}
return 0;
}