NOIP2010 关押罪犯

快排+贪心+并查集
过程:
 从大到小快排一遍,因为要求最大怨气值最小,所以每次要删除边,然后分成两个集合。
 对于之前没有确定关系的两个人,分别确定这两个人为敌人关系(因为数据从大到小保证有序),所以一定不能把他们放在同一监狱。
 对于之前某个人已经确定关系,则让未确定关系的人和已确定关系的人的敌人同属一个集合,让未确定关系的人的敌人和已确定关系的人同属一个集合。
 如果两个人的祖先相同,那么这条边一定是最大的怨气值,输出即可。(因为数据保证有序了。)

program prison; 

type date=record 
		l,r,v:longint; 
	end; 

var 
	a:array[1..100000]of date; 
	fa:array[1..20000]of longint; 
	dui:array[1..20000]of longint; 
	n,m,i,j,ans:longint; 

procedure qsort(he,ti:longint); 
var 
	i,j,x:longint;
	y:date; 
begin 
	i:=he;
	j:=ti;
	x:=a[(i+j)>>1].v; 
	repeat 
		while a[i].v<x do inc(i); 
		while a[j].v>x do dec(j); 
		if i<=j then 
			begin 
				y:=a[i]; 
				a[i]:=a[j]; 
				a[j]:=y; 
				i:=i+1; 
				j:=j-1; 
			end;//if 
	until i>j;//repeat 
	if he<j then qsort(he,j); 
	if i<ti  then qsort(i,ti); 
end;//qsort 
	
function find(x:longint):longint; 
begin 
	if fa[x]=x then exit(x); 
	fa[x]:=find(fa[x]); 
	exit(fa[x]); 
end;//find 
	
procedure union(a,b:longint); 
begin 
	fa[find(a)]:=find(fa[b]); 
end;//union 

begin 
	fillchar(fa,sizeof(fa),0); 
	readln(n,m); 
	for i:=1 to n do fa[i]:=i; 
	for i:=1 to m do readln(a[i].l,a[i].r,a[i].v); 
	qsort(1,m); 
	i:=m; 
	while i>0 do 
		begin 
			if find(a[i].l)=find(a[i].r) then 
				begin 
					ans:=a[i].v;
					break;
				end; 
			if (dui[a[i].l]=0) and (dui[a[i].r]=0) then 
				begin 
					dui[a[i].l]:=a[i].r; 
					dui[a[i].r]:=a[i].l; 
				end
			else 
				begin 
					if dui[a[i].l]<>0 then 
						begin 
							union(dui[a[i].l],a[i].r); 
							if dui[a[i].r]=0 then dui[a[i].r]:=a[i].l; 
						end;
					if dui[a[i].r]<>0 then 
						begin 
							union(dui[a[i].r],a[i].l); 
							if dui[a[i].l]=0 then dui[a[i].l]:=a[i].r; 
						end;
				end;
			dec(i); 
		end;
	writeln(ans); 
end.


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值