您的位置:首页 > 其它

hdu 2489 Minimal Ratio Tree【深搜+最小生成树】

2015-03-23 21:37 513 查看

Minimal Ratio Tree

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2849 Accepted Submission(s): 849



[align=left]Problem Description[/align]
For a tree, which nodes and edges are all weighted, the ratio of it is calculated according to the following equation.



Given a complete graph of n nodes with all nodes and edges weighted, your task is to find a tree, which is a sub-graph of the original graph, with m nodes and whose ratio is the smallest among all the trees of m nodes in the graph.

[align=left]Input[/align]
Input contains multiple test cases. The first line of each test case contains two integers n (2<=n<=15) and m (2<=m<=n), which stands for the number of nodes in the graph and the number of nodes in the minimal ratio tree. Two zeros
end the input. The next line contains n numbers which stand for the weight of each node. The following n lines contain a diagonally symmetrical n×n connectivity matrix with each element shows the weight of the edge connecting one node with another. Of course,
the diagonal will be all 0, since there is no edge connecting a node with itself.

All the weights of both nodes and edges (except for the ones on the diagonal of the matrix) are integers and in the range of [1, 100].

The figure below illustrates the first test case in sample input. Node 1 and Node 3 form the minimal ratio tree.



[align=left]Output[/align]
For each test case output one line contains a sequence of the m nodes which constructs the minimal ratio tree. Nodes should be arranged in ascending order. If there are several such sequences, pick the one which has the smallest node
number; if there's a tie, look at the second smallest node number, etc. Please note that the nodes are numbered from 1 .

[align=left]Sample Input[/align]

3 2
30 20 10
0 6 2
6 0 3
2 3 0
2 2
1 1
0 2
2 0
0 0


[align=left]Sample Output[/align]

1 3
1 2题意:给出n个点,每个点都有权值,给出n*n的矩阵表示点与点边的权值,给出m求其中m个点使m个点组成的树的边的权值之和与点的权值之和比值最小,如果情况有多中则按最小编号的小者输出,如果第一小编号相等,则按第二小编号比较,依次类推。。。分析:由于n比较小所以暴力枚举m个点,去m个点的最小生成树即可。#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#define inf 1000000000
#define eps 1e-9
using namespace std;
const int maxh=20;
int dis[maxh],map[maxh][maxh],pre[maxh],temp[maxh],node[maxh],value[maxh],m,n;
bool pos[maxh];
double M;
int prim(int N)
{
int i,j,k,Min,mst=0;
for(i=2;i<=N;i++)
{
pos[temp[i]]=false;
dis[temp[i]]=map[temp[1]][temp[i]];
pre[temp[i]]=temp[1];
}
dis[temp[1]]=0,pos[temp[1]]=true;
for(i=1;i<=N-1;i++)
{
Min=inf;
for(j=1;j<=N;j++)
if(!pos[temp[j]]&&dis[temp[j]]<Min)
{
Min=dis[temp[j]];
k=temp[j];
}
pos[k]=true;
mst+=Min;
for(j=1;j<=N;j++)
{
if(!pos[temp[j]]&&dis[temp[j]]>map[k][temp[j]])
{
dis[temp[j]]=map[k][temp[j]];
pre[temp[j]]=k;
}
}
}
return mst;
}
void dfs(int k,int num)
{
if(num==m)
{
int sum=0,s=prim(m);
for(int i=1;i<=m;i++)
{
sum+=value[temp[i]];
}
double ans=(double)s/(double)sum;
if(M-ans>eps)
{
M=ans;
for(int i=1;i<=m;i++)
node[i]=temp[i];
}
return;
}
if((k+m-num)>n)return;
for(int i=k+1;i<=n;i++)
{
temp[num+1]=i;
dfs(i,num+1);
}
}
int main()
{
int i,j;
while(~scanf("%d%d",&n,&m)&&(n+m))
{
for(i=1;i<=n;i++)
scanf("%d",&value[i]);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&map[i][j]);
M=inf;
dfs(0,0);
for(int i=1;i<m;i++)
printf("%d ",node[i]);
printf("%d\n",node[m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: