我们根据高度建图,将无向边转化为有向边
首先对于第一问,直接一个bfs搞定,得到ans1
然后第二问,我们就相当于要求找到一颗最小生成树,
满足相对来说深度小的高度大,也就是要以高度为优先级
假设现在有一种添边的方案(一共添ans1-1条,类似于Kruskal的过程)
那么对于添边,我们可以看做是现有一颗树,通过连接一条边将一个点加入到树里的过程
那么对于添加一个点,假设有一种方案先加入X,然后加入Y,HIGH[X]<HIGH[Y]那么肯定
可以找到另一种添加方式,先加入Y,再加入X,因为Y比X高,也就是既然能先加X,X肯定不
影响Y的合法性,也就是以高度为优先级,保证了合法性
那么我们在做Kruskal 的排序的时候,只需要以点(X——>Y,说的是Y点)的高度为第一关键字,
边长为第二关键字就好了。
后来看了网上别人的思路,上面我写的加边的那一部分,可以通过prim来理解,prim就是现在有一个点的集合
然后在剩下的点里找到距离集合最短的一个点加进来,后面高度优先级的证明类似。
/************************************************************** Problem: 2753 User: BLADEVIL Language: Pascal Result: Accepted Time:26668 ms Memory:96420 kb****************************************************************/ //By BLADEVILvar n, m :int64; high :array[0..100010] of int64; pred, succ :array[0..2000010] of int64; len :array[0..2000010] of int64; pre, other, last :array[0..2000100] of int64; l :int64; que :array[0..100010] of int64; ans1, ans2 :int64; flag :array[0..100010] of boolean; father :array[0..100010] of int64; procedure swap(var a,b:int64);var c :int64;begin c:=a; a:=b; b:=c;end; procedure connect(x,y:int64);begin inc(l); pre[l]:=last[x]; last[x]:=l; other[l]:=y;end; procedure init;var i :longint; x, y, z :int64; begin read(n,m); for i:=1 to n do read(high[i]); for i:=1 to m do begin read(x,y,z); if high[x]0 do begin p:=other[q]; if not flag[p] then begin inc(t); flag[p]:=true; que[t]:=p; end; q:=pre[q]; end; end; ans1:=t;end; procedure qs(l,h:int64);var i, j, xx, yy :int64;begin i:=l; j:=h; xx:=high[succ[(i+j) div 2]]; yy:=len[(i+j) div 2]; while i xx) or (high[succ[i]]=xx) and (len[i] yy) do dec(j); if i<=j then begin swap(pred[i],pred[j]); swap(succ[i],succ[j]); swap(len[i],len[j]); inc(i); dec(j); end; end; if i l then qs(l,j);end; function getfather(x:int64):int64;begin if father[x]=x then exit(x); father[x]:=getfather(father[x]); exit(father[x]);end; procedure main;var a, b, fa, fb :int64; i :longint; begin bfs; for i:=1 to n do father[i]:=i; qs(1,m); for i:=1 to m do begin a:=pred[i]; b:=succ[i]; if (not flag[a]) or (not flag[b]) then continue; fa:=getfather(a); fb:=getfather(b); if (fa<>fb)then begin father[fb]:=fa; ans2:=ans2+len[i]; end; end; writeln(ans1,' ',ans2);end; begin init; main;end.