【题意】
k度生成树。
【输入】
第一行:n条边
接下来n行描述边
Park为限度点
【输出】
”Total miles driven: “+最小生成树权值
比较麻烦的一道题
写了4,336 字节
组织的可能不是太好
单纯的讲一下做法
证明黑书上有
1、把跟限度点之间边去掉后生成最小生成树,得到一片森林
2、对于森林里的每棵树,选其中跟限度点有边且该边权值最小的连上
如果有n棵树,则现在则为n度最小生成树
3、接下来就是利用增加度来尝试减少费用了
尝试每条与限度点相连的边,连上该条边理所应当的需要剪短一条从该点到限度点路径上的边
当然是减最大的。
所以每次剪之前,可以做一遍dfs来确定每个点到限度点路径上权值最大的边
总体复杂度O(kn)
就是这样,感觉说的非常不清,不愧是语文期末94的人啊。
program poj1639;
type
node=record
x,y,c:longint;
end;
var
n,i,j,k,t,tot,x,y,c,no,all,ans,now,minn,u,v,maxn:longint;
order,a,b:string;
line:array [0..10001] of node;
temp:node;
trie:array [0..10001,'a'..'z'] of longint;
max,incr,father,who:array [-1..10001] of longint;
nn,last,roo,next,point,cost:array [-1..10001] of longint;
yes:array [-1..10001] of boolean;
procedure swap (var a,b:longint);
var
i:longint;
begin
i:=a;
a:=b;
b:=i;
end;
function find (st:string):longint;
var
i,k:longint;
begin
i:=0;
for k:=1 to length(st) do
begin
if trie[i][st[k]]=0 then
begin
inc(tot);
trie[i][st[k]]:=tot;
end;
i:=trie[i][st[k]];
end;
if who[i]=0 then
begin
inc(no);
who[i]:=no;
end;
exit(who[i]);
end;
procedure qsort (s,e:longint);
var
i,j,k:longint;
begin
if s>=e then exit;
i:=s;
j:=e;
k:=line[(s+e) div 2].c;
while i<=j do
begin
while (i<=j)and(line[i].c<k) do inc(i);
while (i<=j)and(line[j].c>k) do dec(j);
if i>j then break;
temp:=line[i];
line[i]:=line[j];
line[j]:=temp;
inc(i);
dec(j);
end;
qsort(s,j);
qsort(i,e);
end;
function root (now:longint):longint;
begin
if father[now]=0 then exit(now);
father[now]:=root(father[now]);
exit(father[now]);
end;
procedure connect (s,e,c,ll:longint);
begin
inc(all);
point[all]:=e;
cost[all]:=c;
next[all]:=roo[s];
last[roo[s]]:=all;
roo[s]:=all;
nn[all]:=ll;
end;
procedure deletee (now,wh:longint);
begin
if next[now]<>0 then last[next[now]]:=last[now];
if last[now]<>0 then next[last[now]]:=next[now];
if roo[wh]=now then roo[wh]:=next[now];
end;
procedure dfs (now,maxn:longint);
var
i:longint;
begin
yes[now]:=true;
i:=roo[now];
max[now]:=maxn;
while i<>0 do
begin
if not yes[point[i]] then
if cost[i]>cost[maxn] then dfs(point[i],i)
else dfs(point[i],maxn);
i:=next[i];
end;
end;
begin
readln(n);
trie[0,'p']:=1;
trie[1,'a']:=2;
trie[2,'r']:=3;
trie[3,'k']:=4;
tot:=4;
no:=0;
who[4]:=-1;
for i:=1 to n do
begin
readln(order);
a:=copy(order,1,pos(' ',order)-1);
delete(order,1,pos(' ',order));
b:=copy(order,1,pos(' ',order)-1);
delete(order,1,pos(' ',order));
val(order,line[i].c,c);
for j:=1 to length(a) do
if a[j]<='Z' then a[j]:=chr(ord(a[j])+32);
for j:=1 to length(b) do
if b[j]<='Z' then b[j]:=chr(ord(b[j])+32);
line[i].x:=find(a);
line[i].y:=find(b);
if line[i].x>line[i].y then swap(line[i].x,line[i].y);
end;
read(t);
qsort(1,n);
all:=0;
now:=0;
for i:=1 to n do
if (line[i].x<>-1)and(line[i].y<>-1)and(root(line[i].x)<>root(line[i].y)) then
begin
father[root(line[i].x)]:=root(line[i].y);
now:=now+line[i].c;
connect(line[i].x,line[i].y,line[i].c,all+2);
connect(line[i].y,line[i].x,line[i].c,all);
end;
fillchar(incr,sizeof(incr),0);
fillchar(yes,sizeof(yes),false);
k:=0;
for i:=1 to n do
if ((line[i].x=-1)or(line[i].y=-1))and(not yes[root(line[i].x+line[i].y+1)]) then
begin
inc(k);
yes[root(line[i].x+line[i].y+1)]:=true;
incr[root(line[i].x+line[i].y+1)]:=line[i].c;
now:=now+line[i].c;
connect(line[i].x,line[i].y,line[i].c,all+2);
connect(line[i].y,line[i].x,line[i].c,all);
end;
line[0].c:=-maxlongint;
ans:=now;
for i:=k+1 to t do
begin
fillchar(yes,sizeof(yes),false);
maxn:=0;
dfs(-1,0);
for j:=1 to n do
if (line[j].x=-1)and(cost[max[line[j].y]]-line[j].c>maxn) then
begin
maxn:=cost[max[line[j].y]]-line[j].c;
u:=line[j].y;
v:=j;
end;
if maxn=0 then break;
now:=now-maxn;
if now<ans then ans:=now;
deletee(max[u],point[nn[max[u]]]);
deletee(nn[max[u]],u);
connect(line[v].x,line[v].y,line[v].c,all+2);
connect(line[v].y,line[v].x,line[v].c,all);
end;
writeln('Total miles driven: ',ans);
end.