int find(int x)//并查集找父亲
{
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}
void add(int x,int y)//合并
{
int fx=find(x);
int fy=find(y);
if(x!=y) fa[fx]=fy;
}
P1197 [JSOI2008] 星球大战 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
洛谷p1197星球大战 :并查集+逆向思考_phrame_的博客-CSDN博客
这题由于并查集不好进行删除点的操作,所以反向操作,把删除点反向成一个个添加新的点,注意判断连通块的方法是看,fa[i]==i,那么是一个连通块,父亲相等为一个连通块
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+100;
vector<int>ans;
vector<int> a[N];//存图
int fa[N];
int h[N];//存要摧毁的
int vis[N];//标记是否要摧毁
int find(int x)//并查集
{
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}
void add(int x,int y)//合并
{
int fx=find(x);
int fy=find(y);
if(x!=y) fa[fx]=fy;
}
signed main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)
{
fa[i]=i;//初始化
}
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);//双向存图
}
int k;
cin>>k;
for(int i=1;i<=k;i++)
{
cin>>h[i];
vis[h[i]]=1;//标记要摧毁的
}
for(int i=0;i<n;i++)
{
for(auto x:a[i])//遍历a[i]所有的点
{
if(vis[x] ||vis[i])//去掉要摧毁的
{
continue;
}
add(x,i);//对不摧毁的点合并处理
}
}
int cnt=0;
for(int i=0;i<n;i++)
{
if(!vis[i]&&fa[i]==i)
{
cnt++;//没有修复前连通块的个数
}
}
ans.push_back(cnt);//最后一种全摧毁完的答案
//开始修复,倒推
for(int i=k;i>=1;i--)
{
int x=h[i];
cnt++;//把它当成独立的连通块
vis[x]=0;//被修复
for(auto u:a[x])
{
if(!vis[u]&&find(x)!=find(u))
{
add(u,x);
cnt--;//减去不是连通块的
}
}
ans.push_back(cnt);
}
reverse(ans.begin(),ans.end());
for(auto c:ans)
{
cout<<c<<endl;
}
return 0;
}
P1525 [NOIP2010 提高组] 关押罪犯 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
带权并查集,按权值先排序,然后再进行查找,合并等操作,记住合并操作要在根节点上运作
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,f[40005],x,y;
struct data{
int a,b,c;
}e[N];
bool cmp(data p,data q)
{
return p.c>q.c;//从大到小排
}
int find(int x)//并查集,find(x)就是x的根
{
if(f[x]!=x) f[x]=find(f[x]);
return f[x];
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>e[i].a>>e[i].b>>e[i].c;
}
for(int i=1;i<=n*2;i++)
{
f[i]=i;//先预处理每个人指向自己
}
sort(e+1,e+1+m,cmp);
for(int i=1;i<=2*n;i++)
{
//并查集的合并操作都是对根操作
int x=find(e[i].a);
int y=find(e[i].b);
if(x==y)//根相同,代表在同一个集合
{
cout<<e[i].c;
return 0;
}
//合并,a到b的敌人b'集合,b到a的敌人a'集合
f[x]=find(e[i].b+n);
f[y]=find(e[i].a+n);
}
cout<<0;
return 0;
}