8
18
2013
0

【BZOJ1083】【SCOI2005】繁忙的都市【最小生成树】

我是用二分边权然后判联通做的。但是貌似直接用最小生成树就可以。。



program p1083;
	type
		bian=record
			point,next,w,f:longint;
		end;
	var
		b:array[1..50000] of bian;
		p,d:array[1..400] of longint;
		pd:array[1..400] of boolean;
		x:array[1..50000] of longint;
		l,r,mid,ans,i,j,n,m,k1,k2,k3,len:longint;
	procedure ade(k1,k2,k3:longint);
		begin
			inc(len);
			b[len].point:=k2;
			b[len].next:=p[k1];
			b[len].w:=k3;
			p[k1]:=len;
		end;
	procedure add(k1,k2,k3:longint);
		begin
			ade(k1,k2,k3);
			ade(k2,k1,k3);
		end;
	procedure qsort(first,en:longint);
		var
			i,j:longint;
		begin
			i:=first; j:=en; x[0]:=x[i];
			while i<j do begin
				while (i<j) and (b[x[0]].w<=b[x[j]].w) do dec(j);
				if (i<j) then x[i]:=x[j];
				while (i<j) and (b[x[0]].w>b[x[i]].w) do inc(i);
				if i<j then x[j]:=x[i];
			end;
			x[i]:=x[0];
			if i>first+1 then qsort(first,i-1);
			if j<en-1 then qsort(i+1,en);
		end;
	procedure find(k1,k2:longint);
		var
			i,j:longint;
		begin
			pd[k1]:=true;
			i:=p[k1];
			while i>0 do begin
				j:=b[i].point;
				if (b[i].f<=k2) and (pd[j]=false) then
					find(j,k2);
				i:=b[i].next;
			end;
		end;
	function charge:boolean;
		var
			i:longint;
		begin
			for i:=1 to n do
				if pd[i]=false then exit(false);
			exit(true);
		end;
	begin
		readln(n,m);
		len:=0;
		if n=1 then begin
			writeln(0,' ',0);
			exit;
		end;
		fillchar(b,sizeof(b),0);
		fillchar(p,sizeof(p),0);
		for i:=1 to m do begin
			readln(k1,k2,k3);
			add(k1,k2,k3);
		end;
		for i:=1 to len do
			x[i]:=i;
		qsort(1,len);
		for i:=1 to len do
			b[x[i]].f:=i;
		l:=1; r:=len+1;
		while l<r do begin
			mid:=(l+r) div 2;
			fillchar(pd,sizeof(pd),false);
			find(1,mid);
			if charge then begin
				r:=mid;
				ans:=mid;
			end else l:=mid+1;
		end;
		writeln(n-1,' ',b[x[ans]].w);
	end.
Category: 最小生成树 | Tags: | Read Count: 901

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com