acwing836—合并集合
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e5+10;
int n,m;
int p[N];
int find(int x)//返回x的祖宗节点
{
if(x!=p[x])p[x]=find(p[x]); //x只是一个值,
return p[x];//如果写成p[x]=find(x)是不对的,无限递归也能看出来! 左右应该都是p[x]才对
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)p[i]=i;
while(m--)
{
char a[3];
int x,y;
scanf("%s",a);
scanf("%d%d",&x,&y);
if(a[0]=='M')
{
p[find(x)]=find(y);
}
else
{
if(p[find(x)]==p[find(y)])
printf("Yes\n");
else
printf("No\n");
}
}
return 0;
}
acwing837-连通块中点的数量
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+10;
int n,m,p[N],cnt[N];
//cnt[i]表示节点i所在的连通块的点的数量。
int find(int x)
{
if(x!=p[x])
p[x]=find(p[x]);
return p[x];
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{p[i]=i;cnt[i]=1;}
int x,y;
while(m--)
{
char a[4];
cin>>a;
if(a[0]=='C')
{
cin>>x>>y;
/*
if(find(x)!=find(y))//防止重复加边。
{
p[find(x)]=find(y);
cnt[y]+=cnt[x];
}
*/
x = find(x), y = find(y);//x,y是定死的
if (x != y)
{
p[x] = y;
cnt[y] += cnt[x];
}
}
else if(a[1]=='1')//是否在一个集合里边。
{
cin>>x>>y;
if(find(x)==find(y))
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
else//连通块中点的数量。
{
cin>>x;
cout<<cnt[find(x)]<<endl;
}
}
return 0;
}
acwing240—食物链
//y总NB
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=5e4+10;
int n,k,p[N],dis[N];
int find(int x)
{
if(x!=p[x])
{
int t=find(p[x]);
dis[x]+=dis[p[x]];
p[x]=t;
}
return p[x];
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
p[i]=i;
int res=0;
while(k--)
{
int a,b,c;
cin>>a>>b>>c;
if(b>n||c>n){res++;continue;}
int x=find(b),y=find(c);
if(a==1)
{
if(x==y)
{
if((dis[b]-dis[c])%3)
res++;
}
else
{
p[x]=y;
dis[x]= dis[c]-dis[b];//这样res就不用++了
}
}
else
{
if(x==y)//x吃y
{
if((dis[b]-dis[c]-1)%3)
res++;
}
else
{
p[x]=y;
dis[x]=dis[c]+1-dis[b];
}
}
}
cout<<res;
}
kruskal(利用并查集)求最小生成树
//nice 的kruskal
/*
1.将所有边按权重从小到大排序O(mlogm) m常数较小
2.枚举每条边 a <-> b
如果a-b不连通将边加入S中去。
*/
//kruskal适用于稀疏图
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+10,M=2e5+10;
int n,m,st[M],p[N];
struct Edge
{
int a,b,w;
bool operator <(Edge x)
{
return w<x.w;
}
}eage[M];
int find(int x)
{
if(x!=p[x])
{
p[x]=find(p[x]);
}
return p[x];
}
int kruskal()
{
int res=0;
int cnt=0;
for(int i=0;i<m;i++)
{
int x=find(eage[i].a),y=find(eage[i].b);
if(!st[i]&&x!=y)
{
p[x]=y;
res+=eage[i].w;
cnt++;
st[i]=1;
}
}
if(cnt<n-1)
{
cout<<"impossible";
return 2e9;
}
else
return res;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
p[i]=i;
for(int i=0;i<m;i++)
{
int x,y,c;cin>>x>>y>>c;
eage[i]={x,y,c};
}
sort(eage,eage+m);
int t=kruskal();
if(t!=2e9)
cout<<t;
}