并查集
来源:互联网 发布:怎么让数组置空 编辑:程序博客网 时间:2024/05/30 05:00
FZU2155 带删除并查集
HDU 2473 Junk-Mail Filter 并查集删除(FZU 2155盟国)
http://acm.hdu.edu.cn/showproblem.php?pid=2473
http://acm.fzu.edu.cn/problem.php?pid=2155
题目大意:
编号0~n-1的电子邮件,让你进行归类。
M X Y表示x y是同一类的,而S X则取消之前X的分类。问你经过M次这样的操作后,有多少类相同的邮件。
思路:
下午FZU月赛有这题。不过我没参加- -||||,先暂时退出ACM一段时间。事情多。得先去搞定那个外包的软件了
并查集的应用。多开了一个数组real,记录点的真实存在的位置。
一开始初始化为和fa相同的,删除的时候把原来x所在的位置变为新的一个位置即可,那么原来的集合不受影响。
看代码吧。。
#include<cstdio>#include<cstring>const int MAXN=1100010;int fa[MAXN],real[MAXN];bool vis[MAXN];int find(int x){ if(x!=fa[x])fa[x]=find(fa[x]); return fa[x];}int main(){ int n,m,kase=1; while(~scanf("%d%d",&n,&m),n||m) { memset(vis,0,sizeof(vis)); int k=n; for(int i=0;i<n;i++) real[i]=fa[i]=i; char cmd[5]; for(int i=0;i<m;i++) { scanf("%s",cmd); if(cmd[0]=='M') { int a,b; scanf("%d%d",&a,&b); int root_x=find(real[a]),root_y=find(real[b]); if(root_x!=root_y) fa[root_x]=root_y; } else { int a; scanf("%d",&a); fa[k]=k; real[a]=k++; } } int ans=0; for(int i=0;i<n;i++) { int x=find(real[i]); if(!vis[x]) { vis[x]=1; ans++; } } printf("Case #%d: %d\n",kase++,ans); } return 0;}
#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define N 30010int f[N],cnt[N];int n,m;int mfind(int x){ if(f[x]!=x)f[x]=mfind(f[x]); return f[x];}void make(int a,int b){ int f1=mfind(a); int f2=mfind(b); if(f1!=f2) { f[f2]=f1; cnt[f1]+=cnt[f2]; }}int main(){ int i; while(~scanf("%d%d",&n,&m)&&(n+m)) { for(i=0;i<=n;i++){ f[i]=i; cnt[i]=1; } int t,a,b; for(i=0;i<m;i++) { scanf("%d",&t); scanf("%d",&a); t--; while(t--) { scanf("%d",&b); make(a,b); } } int p=mfind(0); printf("%d\n",cnt[p]); // for(i=0;i<100;i++)printf("%d %d\n",i,cnt[i]); } return 0;}
PAT1034 做了这题后对并查集理解更深刻了些
题意:
『gang』翻译过来是『一伙人』。gang 的定义是一群人,至少有 3 个人,这群人中每个人之间都通过通话相连,且整个群体的通话时长超过一个阈值。整个 gang 的团体中,拥有的电话时长最长的人就是头目了。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<map>#define N 1010using namespace std;map<string,string>f,to;map<string,int>cnt,tot,ans,all;map<string,string>::iterator it;map<string,int>::iterator itt;string mfind(string x){ if(f[x]!=x)f[x]=mfind(f[x]); return f[x];}void make(string a,string b,int time){ string f1=mfind(a); string f2=mfind(b); if(f1!=f2) { f[f2]=f1; cnt[f1]+=cnt[f2];//统计点权 all[f1]+=all[f2]+time; return; } all[f1]+=time;//统计边权}int main(){ int n,k; while(~scanf("%d%d",&n,&k)) { f.clear(); cnt.clear(); tot.clear(); ans.clear(); to.clear(); all.clear(); char aa[10],bb[10]; string a,b; int time; for(int i=0;i<n;i++) { scanf("%s%s%d",aa,bb,&time); a=aa; b=bb; if(f[a]==""){ f[a]=a; cnt[a]=1; all[a]=0; } if(f[b]==""){ f[b]=b; cnt[b]=1; all[b]=0; } tot[a]+=time; tot[b]+=time; make(a,b,time); } //*****---如果没有这一步,下面两个案例的输出结果是不一样的 for(it=f.begin();it!=f.end();it++) { it->second=mfind(it->second); } //-- for(it=f.begin();it!=f.end();it++) { if(cnt[it->second]<=2||all[it->second]<=k)continue; if(tot[it->first]>ans[it->second]){ ans[it->second]=tot[it->first]; to[it->second]=it->first; } // cout<<it->first<<" "<<it->second<<" "<<tot[it->first]<<" "<<cnt[it->second]<<" "<<all[it->second]<<endl; } cout<<ans.size()<<endl; for(itt=ans.begin();itt!=ans.end();itt++) { cout<<to[itt->first]<<" "<<cnt[itt->first]<<endl; } } return 0;}/*6 59AAA BBB 10BBB AAA 20AAA CCC 40DDD EEE 5EEE DDD 70BBB DDD 106 59AAA BBB 10BBB AAA 20AAA CCC 40DDD EEE 5BBB DDD 10EEE DDD 70*/
0 0
- HDU3938 并查集 并查集
- 并查集(集并查)
- HDU1232 并查集<并>
- 并查集
- 数据结构-并查集
- 并查集
- 并查集!
- 并查集
- 并查集
- 并查集
- 并查集
- 并查集总结
- 并查集学习
- 并查集
- 并查集
- 并查集
- 所谓并查集
- 并查集
- zookeeper的搭建
- 多态类型
- Winsock服务器设计的四个关键问题
- 网页java servlet JSP 提交表单乱码问题
- VISUAL SVN安装 及客户端使用
- 并查集
- 数据科学之机器学习4:线性回归3
- IOS 使用CoreText实现表情文本URL等混合显示控件
- Apache 目录权限的设置
- Cocos2d-x文件编译错误解决
- C++函数系列篇:函数的默认值+带默认参数的函数
- 补码
- 页面无法回传
- android 模拟器键盘控制键 以及 设置模拟器屏幕大小