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
Data Constraint
对于30%数据,N<=5。
var
        a,b,c,d,e,ans,ans2:longint;
        v:array[1..15]of longint;
        f:array[1..15,1..15]of longint;
        r:array[1..15]of longint;
        p,p1,p2:array[1..15]of boolean;
        u:boolean;
        ans1,ans3:real;
procedure yy;
var
        i,j,mins,minx,miny:longint;
begin
        if u=false then exit;
        mins:=maxlongint;
        for i:=1 to c do
        begin
                for j:=1 to a do
                begin
                        if (f[r[i],j]<mins)and(f[r[i],j]<>0)and(p2[j]=true) then
                        begin
                                mins:=f[r[i],j];
                                minx:=r[i];
                                miny:=j;
                        end;
                end;
        end;
        inc(c);
        p2[miny]:=false;
        r[c]:=miny;
        ans:=ans+f[minx,miny];
        if c=b then
        begin
                ans1:=ans/ans2;
                if ans1<ans3 then
                begin
                        p1:=p;
                        ans3:=ans1;
                end;
                u:=false;
                exit;
        end;
        yy;
        if u=false then
                exit;
end;
procedure pd;
var
        i:longint;
begin
        c:=1;
        for i:=1 to a do
                if p[i]=true then
                begin
                        e:=i;
                        break;
                end;
        fillchar(r,sizeof(r),0);
        p2:=p;
        p2[e]:=false;
        r[c]:=e;
        ans:=0;
        u:=true;
        yy;
end;
procedure ss(i,j:longint);
var
        k:longint;
begin
        if j=b then
                pd;
        if i=a+1 then
                exit;
        if (j<b)and(i<a+1) then
                for k:=1 to 2 do
                begin
                        if (k=1) then
                        begin
                                p[i]:=true;
                                ans2:=ans2+v[i];
                                ss(i+1,j+1);
                                p[i]:=false;
                                ans2:=ans2-v[i];
                        end;
                        if (k=2) then
                                ss(i+1,j);
                end;
end;
begin
        assign(input,'ratio.in');reset(input);
        assign(output,'ratio.out');rewrite(output);
        readln(a,b);
        ans3:=maxlongint;
        for c:=1 to a do
                read(v[c]);
        for c:=1 to a do
        begin
                for d:=1 to a do
                        read(f[c,d]);
                readln;
        end;
        fillchar(p,sizeof(p),false);
        ss(1,0);
        for c:=1 to a do
                if p1[c]=true then
                        write(c,' ');
        close(input);
        close(output); 
end.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值