**【NOIP2013模拟11.6B组】最小比例(ratio) **
Description
图中共有N个点的完全图,每条边都有权值,每个点也有权值。要求选出M个点和M-1条边,构成一棵树,使得:
即所有边的权值与所有点的权值之和的比率最小。
给定N和M,以及N个点的权值,和所有的边权,要求M个点的最小比率生成树。
Input
第一行包含两个整数N和M(2<=N<=15,2<=M<=N),表示点数和生成树的点数。
接下来一行N个整数,表示N个点的边权。
最后N行,每行N列,表示完全图中的边权。所有点权和边权都在[1,100]之间。
Output
输出最小比率生成树的M个点。当答案出现多种时,要求输出的第一个点的编号尽量小,第一个相同,则第二个点的编号尽量小,依次类推,中间用空格分开。编号从1开始。
Sample Input
输入1:
3 2
30 20 10
0 6 2
6 0 3
2 3 0
输入2:
2 2
1 1
0 2
2 0
Sample Output
输出1:
1 3
输出2:
1 2
题解:100%
这道题一看就是一道最小生成树的题目。当然,此题要选M个点和M-1条边。然而数据只有15个点,递归每一个点选不选择,时间2^15当然是可以卡过的。然后,我们就在把每个选择的点进行一个最小生成树,连起来,把相应的∑node和∑edge给求出来,在记录就可以过了。
注意:
本题使用的最小生成树可以为克鲁斯卡尔或普利姆做,还是要掌握滴~
标程(克鲁斯卡尔的方法):
type
new=record
x:longint;
y:longint;
a:longint;
end;
var
i,j,k,l,n,m,nodeans,edgeans,ans,dep:longint;
f,nodejl,node,sans:array[0..100] of longint;
bz:array[0..1000] of boolean;
route:array[0..1000] of new;
map:array[0..100,0..100] of longint;
ratio:extended;
procedure qs(l,r:longint);
var
i,j,mid:longint;
t:new;
begin
i:=l;
j:=r;
mid:=route[(i+j) div 2].a;
repeat
while route[i].a<mid do inc(i);
while route[j].a>mid do dec(j);
if i<=j then
begin
t:=route[i];
route[i]:=route[j];
route[j]:=t;
inc(i);
dec(j)
end
until i>j;
if i<r then qs(i,r);
if l<j then qs(l,j)
end;
function zs(t:longint):longint;
var
i,j,k,l:longint;
begin
l:=t;
while f[t]<>t do
begin
t:=f[t];
end;
while f[l]<>t do
begin
j:=f[l];
f[l]:=t;
l:=j;
end;
zs:=t;
end;
procedure dg(depnode:longint);
var
i,j,k,l,x,y:longint;
begin
if ans=m then
begin
edgeans:=0;
for i:=1 to n do f[i]:=i;
i:=1;
j:=1;
while j<=m-1 do
begin
if (bz[route[i].x])and(bz[route[i].y]) then
if zs(route[i].x)<>zs(route[i].y) then
begin
x:=zs(route[i].x);
y:=zs(route[i].y);
f[x]:=y;
inc(edgeans,route[i].a);
inc(j);
end;
inc(i);
if i>n*n then exit;
end;
if ratio>edgeans/nodeans then
begin
sans:=nodejl;
ratio:=edgeans/nodeans;
end;
edgeans:=0;
end
else
begin
for i:=depnode to n do
begin
if (nodejl[1]=1)and(nodejl[2]=4)and(nodejl[3]=6)
and(nodejl[4]=11)and(nodejl[5]=12)and(nodejl[6]=13)then
nodejl[1]:=1;
bz[i]:=true;
inc(nodeans,node[i]);
inc(ans);
nodejl[ans]:=i;
dg(i+1);
dec(nodeans,node[i]);
nodejl[ans]:=0;
dec(ans);
bz[i]:=false;
end;
end;
end;
begin
assign(input,'ratio.in');reset(input);
assign(output,'ratio.out');rewrite(output);
readln(n,m);
for i:=1 to n do
begin
read(node[i]);
end;
for i:=1 to n do
begin
for j:=1 to n do
begin
read(map[i,j]);
if map[i,j]<>0 then
begin
inc(dep);
route[dep].x:=i;
route[dep].y:=j;
route[dep].a:=map[i,j];
end;
end;
end;
qs(1,dep);
ratio:=maxlongint;
fillchar(bz,sizeof(bz),false);
for i:=1 to n do
begin
bz[i]:=true;
inc(nodeans,node[i]);
nodejl[1]:=i;
ans:=1;
dg(i+1);
dec(nodeans,node[i]);
bz[i]:=false;
end;
for i:=1 to m do write(sans[i],' ');
writeln;
close(input);close(Output);
end.