标签:
终于写了一点干货,这题终于不是水题了
题目大意就是给你一个图,然后找到两点之间所有路径中边权最大值最小的那一条,输出最小值。
一开始一看最大值最小就用二分答案弄了一遍,结果没看数据范围只有40分QAQ
然后正解是先构造一颗最小生成树,再在树上求lca
为什么呢?我是用反证法考虑的。假如由u到v存在一条路径的边权最大值最小,且这条边不在生成树上。【为了放便表示设max(u,v)表示u到v边权的最大值】设这条边连接的点为i,j,首先易知max(u,i)<a(i,j),max(j,v)<a(i,j),又因为最小生成树的性质我们可以知道在树上一定存在一条路径max(i,j)<a(i,j),即一定存在一条更优的路径,这与假设矛盾。
接下来就是写代码了。求lca我用的是tarjan,在树上找到lca之后我是直接求两点到lca的路径,时间非常差但是居然神奇的ac了……果然是数据太弱。同时由于数据太大要写三次邻接表,然后各种麻烦。其实这题思路找出来之后就很明了了,剩下的就是看码力了。具体做法看代码吧,我写的比较丑。
1 program j01; 2 type xx=record 3 lx,rx,da:longint; 4 end; 5 var q,next,data,q1,next1,data1:array[1..400000]of longint; 6 a:Array[1..400000]of xx; 7 head,head1,f,d,fa,fad:array[1..100000]of longint; 8 n,m,j,i,t,qq,x,y,tt:longint; 9 ans:Array[1..100000]of longint; 10 b:array[1..100000]of boolean; 11 12 function max(a,b:longint):longint; 13 begin 14 if a>b then exit(a) else exit(b); 15 end; 16 17 function gff(i:longint):longint;//并查集 18 var x:longint; 19 begin 20 if f[i]=i then exit(i); 21 x:=gff(f[i]); 22 f[i]:=x; 23 exit(x); 24 end; 25 26 procedure mer(i,j:longint);//合并 27 var x,y:longint; 28 begin 29 x:=gff(i); 30 y:=gff(j); 31 f[x]:=y; 32 end; 33 34 procedure add(a,b,c:longint); 35 begin 36 inc(tt); 37 q[tt]:=b; 38 next[tt]:=head[a]; 39 head[a]:=tt; 40 data[tt]:=c; 41 end; 42 43 procedure add1(a,b,c:longint); 44 begin 45 inc(tt); 46 q1[tt]:=b; 47 next1[tt]:=head1[a]; 48 head1[a]:=tt; 49 data1[tt]:=c; 50 end; 51 52 procedure qs(l,r:longint); 53 var i,j,x:longint; 54 y:xx; 55 begin 56 i:=l; 57 j:=r; 58 x:=a[(i+j)div 2].da; 59 repeat 60 while a[i].da<x do inc(i); 61 while x<a[j].da do dec(j); 62 if i<=j then 63 begin 64 y:=a[i]; 65 a[i]:=a[j]; 66 a[j]:=y; 67 inc(i); 68 dec(j); 69 end; 70 until i>j; 71 if i<r then qs(i,r); 72 if l<j then qs(l,j); 73 end; 74 75 procedure kruscal;//求最小生成树 76 var i,j:longint; 77 begin 78 for i:=1 to n do f[i]:=i; 79 fillchar(head,sizeof(head),0); 80 i:=n-1; 81 tt:=0; 82 for j:=1 to m do 83 begin 84 if gff(a[j].lx)<>gff(a[j].rx) then 85 begin 86 mer(a[j].lx,a[j].rx); 87 add(a[j].lx,a[j].rx,a[j].da); 88 add(a[j].rx,a[j].lx,a[j].da); 89 dec(i); 90 end; 91 if i=0 then exit; 92 end; 93 end; 94 95 procedure bbu(i,pre:longint);//构造最小生成树 96 var j:longint; 97 begin 98 fa[i]:=pre; 99 j:=head[i]; 100 while j<>0 do 101 begin 102 if q[j]<>pre then 103 begin 104 add1(i,q[j],data[j]); 105 fad[q[j]]:=data[j]; 106 bbu(q[j],i); 107 end; 108 j:=next[j]; 109 end; 110 end; 111 112 function ss(i,x:longint):longint;//求路径上最大值 113 begin 114 if i=x then exit(0); 115 ss:=max(fad[i],ss(fa[i],x)); 116 end; 117 118 procedure lca(i:longint);//最近公共祖先 119 var j,x:longint; 120 begin 121 j:=head1[i]; 122 while j<>0 do 123 begin 124 lca(q1[j]); 125 mer(q1[j],i); 126 j:=next1[j]; 127 end; 128 j:=head[i]; 129 b[i]:=true; 130 while j<>0 do 131 begin 132 if b[q[j]] then 133 begin 134 x:=gff(q[j]); 135 ans[data[j]]:=max(ss(q[j],x),ss(i,x)); 136 end; 137 j:=next[j]; 138 end; 139 end; 140 141 begin 142 readln(n,m); 143 for i:=1 to m do readln(a[i].lx,a[i].rx,a[i].da); 144 qs(1,m); 145 kruscal; 146 tt:=0; 147 fillchar(head1,sizeof(head1),0); 148 bbu(1,0); 149 fillchar(q,sizeof(q),0); 150 fillchar(head,sizeof(head),0); 151 fillchar(next,sizeof(next),0); 152 tt:=0; 153 readln(qq); 154 for i:=1 to qq do 155 begin 156 readln(x,y); 157 add(x,y,i); 158 add(y,x,i); 159 end; 160 fillchar(b,sizeof(b),false); 161 for i:=1 to n do f[i]:=i; 162 fillchar(d,sizeof(d),0); 163 t:=0; 164 lca(1); 165 for i:=1 to qq do if ans[i]=0 then writeln(‘impossible‘) else writeln(ans[i]); 166 end.
---恢复内容结束---
标签:
原文地址:http://www.cnblogs.com/oldjang/p/5467941.html