第一问dfs不说
第二问很容易让人想到最小树形图,但是我不会,而且时间复杂度也不允许
还有什么不同的方法呢?
首先想到的是prim的思想,设根节点已经确定,其他点未确定
我们就不断从已确定的点延伸,找到到未确定点中高度最高的那个点的最短边距(如果有多个高度相同的点,肯定选边距最短的)
将边距加入ans,并将这个点标为确定,重复上述,知道所有点都确定即可。
这样的算法没有问题,但是复杂度好像仍然不能AC
我们想,既然我们能用类似prim的思想,为什么不用Kruska呢?
Kruskal的问题在于,这个算法是不涉及到边的方向,用这个不能选出符合条件的解
考虑之前我们用类似prim的思想解题的时候,是以点的高度为第一关键字,然后再以距离为第二关键字
在Kruskal对边排序的时候,我们是不是也可以考虑以点的高度为第一关键字,然后以距离为第二关键字排序呢?
就是这样,我们以边的终点高度为第一关键字降序,长度为第二关键字升序排序
然后按最小生成树的方法做就行了。
结果竟然TLE了,仔细对照一下别人的程序发现一直以来我的并查集写的是有问题的
我原来getfather是这么写的
function getf(x:longint):longint;
begin
while fa[x]<>x do x:=fa[x];
exit(x);
end;
而实际上多次调用这个函数,显然会进行很多冗余的运算
而正确的写法应该是
function getf(x:longint):longint;
begin
if fa[x]<>x then fa[x]:=getf(fa[x]);
exit(fa[x]);
end;
这应该才是并查集所谓反阿克曼函数的时间复杂度吧
亡羊补牢,为时不晚;
1 type node=record 2 x,c,y,next:longint; 3 end; 4 5 var a:array[0..2000010] of node; 6 fa,p,q,h:array[0..110010] of longint; 7 v:array[0..110010] of boolean; 8 len,x,y,z,n,m,i,j,k1,k2,t:longint; 9 ans,e:int64; 10 11 procedure swap(var a,b:node); 12 var c:node; 13 begin 14 c:=a; 15 a:=b; 16 b:=c; 17 end; 18 19 function getf(x:longint):longint; 20 begin 21 if fa[x]<>x then fa[x]:=getf(fa[x]); //唉 22 exit(fa[x]); 23 end; 24 25 procedure add(x,y,z:longint); 26 begin 27 inc(len); 28 a[len].y:=y; 29 a[len].c:=z; 30 a[len].x:=x; 31 a[len].next:=p[x]; 32 p[x]:=len; 33 end; 34 35 procedure bfs; 36 var i,f,x,y:longint; 37 begin 38 t:=1; 39 q[1]:=1; 40 v[1]:=true; 41 f:=1; 42 while f<=t do 43 begin 44 x:=q[f]; 45 i:=p[x]; 46 while i<>-1 do 47 begin 48 y:=a[i].y; 49 if not v[y] then 50 begin 51 v[y]:=true; 52 inc(t); 53 q[t]:=y; 54 end; 55 i:=a[i].next; 56 end; 57 inc(f); 58 end; 59 end; 60 61 procedure sort(l,r:longint); 62 var i,j,x,y,z:longint; 63 begin 64 i:=l; 65 j:=r; 66 x:=a[(l+r) shr 1].c; 67 y:=a[(l+r) shr 1].y; 68 repeat 69 while (h[a[i].y]>h[y]) or (h[a[i].y]=h[y]) and (a[i].c<x) do inc(i); 70 while (h[y]>h[a[j].y]) or (h[a[j].y]=h[y]) and (x<a[j].c) do dec(j); 71 if not(i>j) then 72 begin 73 swap(a[i],a[j]); 74 inc(i); 75 j:=j-1; 76 end; 77 until i>j; 78 if l<j then sort(l,j); 79 if i<r then sort(i,r); 80 end; 81 82 83 begin 84 fillchar(p,sizeof(p),255); 85 readln(n,m); 86 len:=0; 87 for i:=1 to n do 88 read(h[i]); 89 for i:=1 to m do 90 begin 91 readln(x,y,z); 92 if h[x]>h[y] then add(x,y,z) 93 else begin 94 add(y,x,z); 95 if h[x]=h[y] then add(x,y,z); 96 end; 97 end; 98 bfs; 99 sort(1,len); 100 for i:=1 to n do 101 fa[i]:=i; 102 i:=0; 103 j:=0; 104 for j:=1 to len do 105 begin 106 if not(v[a[j].x] and v[a[j].y]) then continue; //首先必须是能访问到的点 107 k1:=getf(a[j].x); 108 k2:=getf(a[j].y); 109 if k1<>k2 then 110 begin 111 fa[k2]:=k1; 112 e:=a[j].c; 113 ans:=ans+e; 114 inc(i); 115 end; 116 end; 117 writeln(t,' ',ans); 118 end.