标签:
第二篇题解依旧是个水题题目依旧不贴,戳这里
这一题正解就是最小生成树,非常简单非常水……安徽省赛什么时候也能出这么水的题QAQ
然而!最小生成树什么的太low了,最大值最小嘛,我一下就嗅到了浓浓的二分答案的味道,再看一下范围,够,好,那就开始好(作)好(死)写一回代码
首先将所有的边全部读进来,然后排序,二分的就是最大的边在这些边中是第几大的。判断可行性的方法:用并查集,将所有小于当前边的边扫描一遍,然后在只包含这些边的图中判断是否只有一个连通块(就是是否全部联通),用并查集来实现,最后l=r时输出
【关于为什么直接最小生成树就可以】首先如果使图联通最少需要n-1条边,再想想克鲁斯卡尔算法,即最小生成树所产生的n-1条边是满足所有点联通情况下的花费最小的情况,这时树里的最大的边就是答案。
下面代码
1 program j01; 2 type xx=record 3 x,y,da:longint; 4 end; 5 var f:array[1..500]of longint; 6 a:array[1..50000]of xx; 7 i,j,n,m,ans:longint; 8 procedure qs(l,r:longint); 9 var x1,i,j:longint; 10 yy:xx; 11 begin 12 i:=l; 13 j:=r; 14 x1:=a[(l+r)div 2].da; 15 repeat 16 while a[i].da<x1 do inc(i); 17 while x1<a[j].da do dec(j); 18 if i<=j then 19 begin 20 yy:=a[i]; 21 a[i]:=a[j]; 22 a[j]:=yy; 23 inc(i); 24 dec(j); 25 end; 26 until i>j; 27 if i<r then qs(i,r); 28 if l<j then qs(l,j); 29 end; 30 function gg(i:longint):longint; 31 var x:longint; 32 begin 33 if f[i]=i then exit(i); 34 x:=gg(f[i]); 35 f[i]:=x; 36 exit(x); 37 end; 38 procedure merge(i,j:longint); 39 var x,y:longint; 40 begin 41 x:=gg(i); 42 y:=gg(j); 43 f[x]:=y; 44 end; 45 function pd(q:longint):boolean; 46 var s,i:longint; 47 begin 48 s:=0; 49 for i:=1 to n do f[i]:=i; 50 for i:=1 to q do 51 if gg(a[i].x)<>gg(a[i].y) then 52 begin 53 inc(s); 54 merge(a[i].x,a[i].y); 55 end; 56 if s=n-1 then exit(true) else exit(false); 57 end; 58 procedure di(l,r:longint); 59 var mid:longint; 60 begin 61 if l=r then 62 begin 63 writeln(a[l].da); 64 halt; 65 end; 66 mid:=(l+r)div 2; 67 if pd(mid) then di(l,mid) else di(mid+1,r); 68 end; 69 begin 70 readln(n,m); 71 for i:=1 to m do readln(a[i].x,a[i].y,a[i].da); 72 qs(1,m); 73 write(n-1,‘ ‘); 74 di(1,m); 75 end.
标签:
原文地址:http://www.cnblogs.com/oldjang/p/5451816.html