题意:n块农田,全部灌水。有两种方式:(1)在第n块天上花费wi建造一个水库(2)从另一块田j花费Pij引水,求最小花费
MST好题
如果没有可以建造水库的条件,那么就是一个最小生成树,没毛病╮(╯_╰)╭
然而加上这个条件以后,相当于可以自己向自己引水花费为wi
加一个超级源点,并向n个点连边为wi,然后对这n+1个点跑最小生成树即可
编程难度为0,但是想到超级源点的难度还是不小的,超级源点在MST、网络流、差分约束系统...应用还是满广的还很灵活
type
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.
——by EIrlys