您的位置:首页 > 其它

NOIP2013模拟最小比例

2016-06-29 19:57 141 查看

题目

图中共有N个点的完全图,每条边都有权值,每个点也有权值。要求选出M个点和M-1条边,构成一棵树,使得:所有边的权值与所有点的权值之和的比率最小。

样例输入:第一行包含两个整数N和M(2<=N<=15,2<=M<=N),表示点数和生成树的点数。

接下来一行N个整数,表示N个点的边权。

最后N行,每行N列,表示完全图中的边权。所有点权和边权都在[1,100]之间。

3 2

30 20 10

0 6 2

6 0 3

2 3 0

样例输出:输出最小比率生成树的M个点。当答案出现多种时,要求输出的第一个点的编号尽量小,第一个相同,则第二个点的编号尽量小,依次类推,中间用空格分开。编号从1开始。

1 3

————————————华丽分割线———————————

剖解题目:不用剖了,题目讲的很明白了。

思路:看到了选的边比点要少一个,自然而然想到了最小生成树(MST)。

解法:考虑到N,M的值特别特别小,呵呵呵呵呵呵呵呵,还用说是什么方法吗?

直接暴力出要选的点,每次选完M个做一次MST,更新答案。

时间复杂度:最坏情况下也就是2n*m log m。1ms内应该可以出街吧?如果过不了,自认倒霉吧。

代码(pascal)

type
arr1=array[1..15]of longint;
arr2=array[1..15]of boolean;
var
n,m,i,j,s:longint;
ans:extended;
a:array[0..20,0..20]of longint;
b,d,c,t1:arr1;
bz:arr2;
function
min1(a,b:longint):longint;
begin
if a<b then exit(a)
else exit(b);
end;
function
maketree(t:arr1; bz:arr2):longint;
var
i,j,k,l,min:longint;
begin
maketree:=0;
fillchar(t,sizeof(t),0);
fillchar(bz,sizeof(s),false);
t[1]:=1;
bz[1]:=true;
k:=1;
while k<m do
begin
inc(k);
min:=maxlongint;
for i:=1 to k-1 do
for j:=1 to m do
if bz[j]=false then
begin
if min>a[d[t[i]],d[j]] then
begin
min:=a[d[t[i]],d[j]];
l:=j;
end;
end;
t[k]:=l;
bz[l]:=true;
maketree:=maketree+min;
end;
end;
procedure
dfs(x,y,z:longint);
var
i:longint;
t:extended;
begin
if x>m then
begin
s:=maketree(t1,bz);
t:=s/z;
if t<ans then
begin
ans:=t;
c:=d;
end;
exit;
end;
for i:=y+1 to n-m+x do
begin
d[x]:=i;
dfs(x+1,i,z+b[i]);
end;
end;
begin
assign(input,'ratio.in'); reset(input);
assign(output,'ratio.out'); rewrite(output);
readln(n,m);
for i:=1 to n do
read(b[i]);
for i:=1 to n do
for j:=1 to n do
read(a[i,j]);
ans:=maxlongint;
dfs(1,0,0);
for i:=1 to m do
write(c[i],' ');
close(input); close(output);
end.


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  最小生成树