p1694猴子 并查集

有n只猴子,第一只尾巴挂在树上,剩下的n-1只,要么被其他的猴子抓住,要么抓住了其他的猴子,要么两者均有。

当然一只猴子最多抓两只另外的猴子,因为只有两只猴爪子嘛。现在给出这n只猴子抓与被抓的信息,并且在某个时刻可能某只猴子会放掉它左手或右手的猴子,导致某些猴子落在地上。求每只猴子落地的时间。

题解:

并查集,路径压缩的时候需要对每个点的答案进行一个min操作;

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<iomanip>
#include<stack>
using namespace std;
#define FILE "dealing"
#define up(i,j,n) for(int i=(j);i<=(n);i++)
#define pii pair<int,int>
#define LL int
#define mem(f,g) memset(f,g,sizeof(f))
namespace IO{
	char buf[1<<15],*fs,*ft;
	int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;}
	int read(){
		int ch=gc(),f=0,x=0;
		while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=1;ch=gc();}
		while(ch>=‘0‘&&ch<=‘9‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=gc();}
		return f?-x:x;
	}
	int readint(){
		int ch=getchar(),f=0,x=0;
		while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=1;ch=getchar();}
		while(ch>=‘0‘&&ch<=‘9‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();}
		return f?-x:x;
	}
}using namespace IO;
const int maxn=401000,inf=100000000;
int n,m,M;
int c[maxn][2],ch[maxn][2],t[maxn][2],r[maxn];
int x,y,fa[maxn],ans[maxn];
pii getfa(int x){
	if(fa[x]==x)return make_pair(x,ans[x]);
	pii y=getfa(fa[x]);
	ans[x]=min(y.second,ans[x]);
	fa[x]=y.first;
	return make_pair(fa[x],ans[x]);
}
void Union(int x,int y,int c){
	x=getfa(x).first,y=getfa(y).first;
	if(x==y)return;
	if(x==1){
		fa[y]=1;
		ans[y]=c;
	}
	else if(y==1){
		fa[x]=1;
		ans[x]=c;
	}
	else fa[x]=y;
	return;
}
int main(){
	n=read(),m=read();
	up(i,1,n)fa[i]=i;
	up(i,1,n)c[i][0]=ch[i][0]=read(),c[i][1]=ch[i][1]=read();
	up(i,1,m){
		x=read(),y=read()-1;
		if(ch[x][y]!=-1)t[++M][0]=x,t[M][1]=y,r[M]=i,ch[x][y]=-1;
	}
	up(i,1,n)ans[i]=m;
	up(i,1,n){
		if(ch[i][0]!=-1)Union(i,ch[i][0],m);
		if(ch[i][1]!=-1)Union(i,ch[i][1],m);
	}
	for(int i=M;i>=1;i--){
		x=t[i][0],y=t[i][1];
		y=getfa(c[x][y]).first,x=getfa(x).first;
		Union(x,y,r[i]-1);
	}
	up(i,1,n)getfa(i);
	up(i,1,n)printf("%d%c",ans[i]==m?-1:ans[i],‘\n‘);
	return 0;
}

  

时间: 2024-11-07 23:01:59

p1694猴子 并查集的相关文章

猴子大王Monkey King 左偏树+并查集维护

Description Once in a forest, there lived N aggressive monkeys. At the beginning, they each does things in its own way and none of them knows each other. But monkeys can't avoid quarrelling, and it only happens between two monkeys who does not know e

hdu1512 Monkey King(并查集,左偏堆)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1512 题目大意:有n个猴子,一开始每个猴子只认识自己.每个猴子有一个力量值,力量值越大表示这个猴子打架越厉害.如果2个猴子不认识,他们就会找他们认识的猴子中力量最大的出来单挑,单挑不论输赢,单挑的2个猴子力量值减半,这2拨猴子就都认识了,不打不相识嘛.现在给m组询问,如果2只猴子相互认识,输出-1,否则他们各自找自己认识的最牛叉的猴子单挑,求挑完后这拨猴子力量最大值. /* 每次给出要争吵的猴子a和

zoj 2334 Monkey King/左偏树+并查集

原题链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1389 大致题意:N只相互不认识的猴子(每只猴子有一个战斗力值) 两只不认识的猴子之间发生冲突,两只猴子会分别请出它们认识的最强壮的 猴子进行决斗.决斗之后这,两群猴子都相互认识了. 决斗的那两只猴子战斗力减半...有m组询问 输入a b表示猴子a和b发生了冲突,若a,b属于同一个集合输出-1 否则输出决斗之后这群猴子(已合并)中最强的战斗力值... 具体思路:用并查

HDU 1512 并查集+左偏树

Monkey King Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3105    Accepted Submission(s): 1330 Problem Description Once in a forest, there lived N aggressive monkeys. At the beginning, they e

HDU ACM 1512 Monkey King-&gt;左偏树+并查集

题意:一开始有N只猴子,,每只都有一个力量值.,并且互不认识,后来 它们之间发生了M次斗争. 每次两次两只猴子a,b斗争是, a和 b都会从他们自己的朋友圈里拉出一个最强的朋友, 之后最强的这两只猴子打, 打完后两只猴子的力量值分别减半..并且 两只猴子的朋友圈的所有人都互相认识(也就是以后不会再打了).问题是对于每次斗争, 若a,b是朋友, 那么输出-1, 否则输出斗争后它们的朋友圈里最强猴子的力量值. 分析:要表示集合的合并查找操作就是并查集最好了:要维护每次的最大值,就可以使用大顶堆,但还

zoj2334 Monkey King , 并查集,可并堆,左偏树

提交地址:点击打开链接 题意:  N(N<=10^5)只猴子,初始每只猴子为自己猴群的猴王,每只猴子有一个初始的力量值.这些猴子会有M次会面.每次两只猴子x,y会面,若x,y属于同一个猴群输出-1,否则将x,y所在猴群的猴王的力量值减半,然后合并这两个猴群.新猴群中力量值最高的为猴王.输出新猴王的力量值. 分析:涉及集合的查询,合并,取最值. 利用并查集和左偏树即可解决. #include <cstdio> #include <cstring> #include <io

CodeForces 745C Hongcow Builds A Nation 并查集

题意: 给了你n个城市 m条边 k个政府 每个政府管辖的区域内不能和其他政府的区域有相连 即政府之间不存在路径 问你在维护这种关系的同时 最多再加多少条边 思路: 先找出来每个联通块 再找出来没有归属的孤立的点 把他们都放到最大的联通块里 然后每个联通块之间的点两两连边是n*(n-1)/2条边 最后算出来的ans-m就好了 (看别人的博客学了一个max_element 1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a

并查集(个人模版)

并查集: 1 int find(int a) 2 { 3 int r=a; 4 while(f[r]!=r) 5 r=f[r]; 6 int i=a; 7 int j; 8 while(i!=r) 9 { 10 j=f[i]; 11 f[i]=r; 12 i=j; 13 } 14 return r; 15 } 16 int merge(int a,int b) 17 { 18 int A,B; 19 A=find(a); 20 B=find(b); 21 if(A!=B) 22 { 23 f[B

并查集应用

题目描述: One way that the police finds the head of a gang is to check people's phone calls. If there is a phone call between A and B, we say that A and B is related. The weight of a relation is defined to be the total time length of all the phone calls