【并查集】猴子
来源:互联网 发布:单片机控制24v继电器 编辑:程序博客网 时间:2024/06/11 17:56
题目描述
有N只猴子,第一只尾巴挂在树上,剩下的N-1只,要么被其他的猴子抓住,要么抓住了其他的猴子,要么两者均有。当然一只猴子最多抓两只另外的猴子。现在给出这N只猴子抓与被抓的信息,并且在某个时刻可能某只猴子会放掉它其中一只手的猴子,导致某些猴子落地。求每只猴子落地的时间。
输入输出格式
输入格式:第一行两个数N、M,表示有N只猴子,并且总时间为M-1。接下来N行,描述了每只猴子的信息,每行两个数,分别表示这只猴子左手和右手抓的猴子的编号,如果是-1,表示该猴子那只手没抓其他猴子。再接下来M行,按时间顺序给出了一些猴子放手的信息,第1+N+i行表示第i-1时刻某只猴子的放手信息,信息以两个数给出,前者表示放手的猴子编号,后者表示其放的是哪只手,1左2右。
【数据规模】
30%的数据,N≤1000,M≤1000;
100%的数据,1≤N≤200000,1≤M≤400000。
输出格式:共输出N行,第i行表示第i只猴子掉落的时刻,若第i只猴子岛M-1时刻以后还没掉落,就输出-1。
输入输出样例
输入样例#1:
3 2-1 33 -11 21 23 1
输出样例#1:
-111
分析:这题其实就是个无向的连通图,求删除一条边后图的连通性。
正向去删边判断确实有点麻烦,我们不妨把操作存起来,从最后一个操作开始逆向加边,
当两个点第一次连通时,就是那两只猴子掉下来的时候。
这里用到带权并查集,也是把每个点的权值都赋为他祖宗的权值,而权值就是掉下来的时间。
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <queue>#include <set>#include <map>#include <vector>#include <list>#define Open(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);#define Close fclose(stdin);fclose(stdout);#define rep(i,m,n) for(int i=m;i<=n;i++)#define dop(i,m,n) for(int i=m;i>=n;i--)#define lowbit(x) (x&(-x))#define ll long long#define INF 2147483647using namespace std;inline int read(){ //快读 int s=0,w=1; char ch=getchar(); while(ch<='0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;}const int maxn=200010;const int maxm=400010;int n,m;int s[2][maxn],f[maxn],ans[maxn]; //s存左右儿子,s[0]是左,s[1]是右,f:并查集,ans:答案 bool v[2][maxn]; //v存要断的边,和邻接矩阵原理一样struct fame{int f,s;}e[maxm];int find(int x){ //带权并查集 if(f[x]==x) return x; int temp=find(f[x]); ans[x]=min(ans[x],ans[f[x]]); return f[x]=temp;}void get_fa(int x,int y,int z){ //x,y是要连的两只猴子,z是时间 x=find(x),y=find(y); if(x!=y){ if(x==1) f[y]=x,ans[y]=z; else f[x]=y,ans[x]=z; }}int main(){ n=read();m=read(); for(int i=1;i<=n;i++){ s[0][i]=read();s[1][i]=read(); f[i]=i;ans[i]=maxm; } for(int i=1;i<=m;i++){ scanf("%d%d",&e[i].f,&e[i].s); v[e[i].s-1][e[i].f]=1; } for(int i=1;i<=n;i++){ if(!v[0][i]&&s[0][i]!=-1) get_fa(i,s[0][i],m); //把有的边连上 if(!v[1][i]&&s[1][i]!=-1) get_fa(i,s[1][i],m); } for(int i=1;i<=n;i++) ans[i]=maxm; //初始值赋为一个极大数 for(int i=m;i>=1;i--) if(s[e[i].s-1][e[i].f]!=-1) get_fa(e[i].f,s[e[i].s-1][e[i].f],i-1); //逆向连边,更新ans for(int i=1;i<=n;i++) find(i),printf("%d\n",ans[i]==maxm?-1:ans[i]); return 0;}
阅读全文
0 0
- 【并查集】猴子
- COGS 2043 猴子 并查集
- bzoj 2429: [HAOI2006]聪明的猴子 并查集
- 【例题】【并查集】NKOJ2107 可爱的猴子
- NKOJ 2107 可爱的猴子(并查集)
- HDU3938 并查集 并查集
- 并查集(集并查)
- HDU1232 并查集<并>
- 并查集
- 数据结构-并查集
- 并查集
- 并查集!
- 并查集
- 并查集
- 并查集
- 并查集
- 并查集总结
- 并查集学习
- storm(1.0.3版本)系统中消息传递过程图
- 交换排序(冒泡排序,快速排序)
- 高软实验二报告
- csdn快速转载
- 笔记本无线网通过网线共享给没有无线网卡的台式机
- 【并查集】猴子
- [PAT]1018. Public Bike Management (30)@Java
- 教你50行代码实现前端路由小轮子
- spring mvc 的全部约束
- Spark-1.6.1 Hadoop-2.6.4 VMware Ubuntu 分布式集群搭建 全过程
- Linux下Redis的安装和部署
- struts+spring+hibernate登录功能包括简单增删改查
- 83. Remove Duplicates from Sorted List
- webWoker