bzoj 1601 最小生成樹經典題
阿新 • • 發佈:2019-01-06
題意:n塊農田,全部灌水。有兩種方式:(1)在第n塊天上花費wi建造一個水庫(2)從另一塊田j花費Pij引水,求最小花費
MST好題
如果沒有可以建造水庫的條件,那麼就是一個最小生成樹,沒毛病╮(╯_╰)╭
然而加上這個條件以後,相當於可以自己向自己引水花費為wi
加一個超級源點,並向n個點連邊為wi,然後對這n+1個點跑最小生成樹即可
程式設計難度為0,但是想到超級源點的難度還是不小的,超級源點在MST、網路流、差分約束系統...應用還是滿廣的還很靈活
——by EIrlystype rec=record a,b,len:longint; end; var n,m,ta,tb,ans :longint; ss,tt :longint; f :array[0..90010] of longint; l :array[0..50010] of rec; i,j :longint; map :array[0..310,0..310] of longint; function get_father(x:longint):longint; begin if x=f[x] then exit(x); f[x]:=get_father(f[x]); exit(F[x]); end; procedure sort(ll,rr:longint); var i,j:longint; x:longint; y:rec; begin i:=ll; j:=rr; x:=l[(ll+rr)>>1].len; while (i<=j) do begin while l[i].len<x do inc(i); while l[j].len>x do dec(j); if (i<=j) then begin y:=l[i]; l[i]:=l[j]; l[j]:=y; inc(i); dec(j); end; end; if i<rr then sort(i,rr); if j>ll then sort(ll,j); end; begin read(n); ss:=n+1; for i:=1 to n+1 do f[i]:=i; for i:=1 to n do begin read(l[i].len); l[i].a:=ss; l[i].b:=i; end; m:=n; for i:=1 to n do for j:=1 to n do read(map[i,j]); for i:=1 to n do for j:=i+1 to n do begin inc(m); l[m].len:=map[i,j]; l[m].a:=i; l[m].b:=j; end; sort(1,m); tt:=0; for i:=1 to m do begin ta:=get_father(l[i].a); tb:=get_father(l[i].b); if (ta<>tb) then begin inc(tt); f[ta]:=tb; inc(ans,l[i].len); if tt=n then break; end; end; writeln(ans); end.