并查集
来源:互联网 发布:spark als推荐算法 编辑:程序博客网 时间:2024/06/07 11:18
家族
#include<cstdio>using namespace std;int n,m,x,y,ans=0,fa[110000];int find(int x){//寻找祖先 if(fa[x]!=x)fa[x]=find(fa[x]); return fa[x];}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); int fx=find(x), fy=find(y); if(fx!=fy)fa[fx]=fy; } for(int i=1;i<=n;i++) if(fa[i]==i)ans++; printf("%d\n",ans); return 0;}
银河英雄传说
#include<bits/stdc++.h>using namespace std;int fa[30001],front[30001],num[30001],x,y,i,j,n,T,ans; //fa[i]表示飞船i的祖先//front[i]表示飞船i与其所在列队头的距离 //num[i]表示第i列的飞船数量 char ins;int find(int n){ //查找祖先的函数 if(fa[n]==n)return fa[n]; int fn=find(fa[n]); //先递归找到祖先 front[n]+=front[fa[n]]; //在回溯的时候更新front(因为更新时要用到正确的front[祖先], //所以只能在回溯的时候更新) return fa[n]=fn;}int main(){ cin>>T; for(i=1;i<=30000;++i){ //定初值 fa[i]=i; front[i]=0; num[i]=1; } while(T--){ cin>>ins>>x>>y; int fx=find(x); //fx为x所在列的队头 int fy=find(y); //fy同上 if(ins=='M'){ front[fx]+=num[fy]; //更新front[x所在列队头(现在在y所在队列后面)]//即加上y所在队列的长度 fa[fx]=fy; //将fy设为fx的祖先 num[fy]+=num[fx]; //更新以fy为队头队列的长度 num[fx]=0; //以fx为队头的队列已不存在,更新 } if(ins=='C'){ if(fx!=fy)cout<<"-1"<<endl; //若x和y的祖先不相同,则不在同一列 else cout<<abs(front[x]-front[y])-1<<endl; //否则利用x和y离队头的距离算//出它们的距离 } } return 0;}
星球大战
#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int MAXI=4e5+4;int f[MAXI],head[MAXI],h[MAXI],ans[MAXI],En=0;//f为并查集,h为打击点存储的数组,ans为每次打击后的答案 bool e[MAXI]; //e来判断是否被打击掉 int find(int x){ if(x!=f[x]) f[x]=find(f[x]); //并查集基本函数 return f[x];}struct edge{ int from; int to; //定义一个结构体来存储邻接表 int next;}a[MAXI];void insert(int u,int v){ //邻接表存储数据 a[En].from=u; a[En].next=head[u]; a[En].to=v; head[u]=En; En++;}int main(){ int n,m,k,x,y,tot,i,u; cin>>n>>m; for(i=0;i<n;++i) { f[i]=i; head[i]=-1; } for(i=0;i<m;++i) { cin>>x>>y; insert(x,y);insert(y,x); //双向存储数据 } cin>>k; tot=n-k; //打击k次后所剩下的点 for(i=1;i<=k;i++) { cin>>x; e[x]=true; //被打击掉后就true,并把打击的点存储到h中 h[i]=x; } for(i=0;i<2*m;i++) { if(e[a[i].from]==false&&e[a[i].to]==false) //如果都没有被打击 { if(find(a[i].from)!=find(a[i].to)) //且之前没有连通 { tot--; //合并这两个点并在总数减去一个 f[find(a[i].from)]=f[find(a[i].to)]; } } } ans[k+1]=tot; //这时为打击k次之后所剩下的连通块 for(int t=k;t>=1;t--) //从后往前“修复” { u=h[t]; tot++; //因为“修复”这个点所以多了一个点,现在总数加 1 e[u]=false; //false表示这个点没有被打击 for(i=head[u];i!=-1;i=a[i].next) //邻接表遍历它所连着的点 { if(e[a[i].to]==false&&f[find(u)]!=f[find(a[i].to)]) //如果被连通的点没有被打击并且之前没有连通 { tot--; //合并 f[find(a[i].to)]=f[find(u)]; //注意尽量不要到过来赋值,这样会不断改变father } } ans[t]=tot; //每“修复”一个点后的有的连通块 } for(i=1;i<=k+1;++i) cout<<ans[i]<<endl; return 0;}
阅读全文
0 0
- HDU3938 并查集 并查集
- 并查集(集并查)
- HDU1232 并查集<并>
- 并查集
- 数据结构-并查集
- 并查集
- 并查集!
- 并查集
- 并查集
- 并查集
- 并查集
- 并查集总结
- 并查集学习
- 并查集
- 并查集
- 并查集
- 所谓并查集
- 并查集
- Codeforces Gym 101164I Cubes
- HDU 5974 A Simple Math Problem
- BZOJ 3527 快速傅里叶变换
- 数据库视频总结(二)
- 有序列表,无序列表,以及框架集
- 并查集
- POJ-2391 Ombrophobic Bovines (二分答案+Floyd+拆点+最大流)
- 关于const的相关知识
- javascript中==与===的区别
- 习题七
- Linux下ssh登陆密码端口用户等基本修改
- Ubuntu 16.04 启动栏或者状态栏的位置切换命令
- Codeforces Round #437 (Div. 2) B. Save the problem!
- 五、My SQL 数据库 (一)建表规约