【HDU2489】Minimal Ratio Tree

Minimal Ratio Tree

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

Total Submission(s): 3057    Accepted Submission(s): 917

Problem Description

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.

Input

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.

Output

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 .

Sample Input

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

Sample Output

1 3
1 2

题意:在一个n个点的图中取出m个点的生成树 每个点和边都有相应的权值  当前m个点的树  根据题中所给计算公式求出当前ratio最小的那个生成树 并按照点的顺序输出当前生成树中的点

题解:因为数据量不大的缘故  可以DFS遍历所有的点   用Prim算法求出最小生成树边的和 之后带入公式中 比较大小 最后找到ratio最小的情况

因为最小值的精度问题调了一晚上 不过还好一次AC

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int maxn = 15+11;
const int inf = 0x7ffffff;
int n, m;
int edge[maxn][maxn], node[maxn], dist[maxn], temp[maxn], tree[maxn];   //edge-边  node-点 dist-Prim算法存放路径 temp-存放最小生成树用到的点 tree-存放最终答案的点
bool mark[maxn];                //标记
double minratio;                //最小值

void dfs(int k, int num);       //深搜
int prim(int u);                //Prim

int main(){
    while(scanf("%d%d", &n, &m)!=EOF && (n&&m)){        //输入nm
        minratio = inf * 1.0;                           //最小值赋初值
        for(int i = 1; i <= n; ++i){
            scanf("%d", &node[i]);                      //输入点
        }
        for(int i = 1; i <= n; ++i){
            for(int j = 1; j <= n; ++j){
                scanf("%d", &edge[i][j]);               //输入边
            }
        }

        for(int i = 1; i <= n; ++i){                    //取出起始点并进入DFS
            temp[1] = i;
            dfs(i, 1);
        }
        for(int i = 1; i < m; ++i){                     //格式化输出
            printf("%d ", tree[i]);
        }
        printf("%d\n", tree[m]);
    }
    return 0;
}

void dfs(int k, int num){
    if(num == m){                                       //m个点 则 进入判断
        int sum = 0;                                    //存放点的权值和
        for(int i = 1; i <= m; ++i){
            sum += node[temp[i]];
        }
        double Ratio = prim(k) * 1.0 / sum;             //Prim取出最小边的和 根据题目中所给的求出ratio
        if(Ratio - minratio<-(1e-9)){                   //因为浮点数 判断大小注意精度
            minratio = Ratio;
            for(int i = 1; i <= m; ++i){                //tree收入当前最小值的点
                tree[i] = temp[i];
            }
        }
        return ;
    }

    for(int i = k+1; i <= n; ++i){                      //如果点的数目不足m  则 继续DFS
        temp[num+1] = i;
        dfs(i, num+1);
    }
}

int prim(int u){
    for(int i = 1; i <= n; ++i){
        dist[temp[i]] = edge[u][temp[i]];               //dist赋值
    }
    memset(mark, false, sizeof(mark));                  //标记赋初值

    int sum = 0;
    mark[u] = true;                                     //已经放入最小生成树的点
    dist[u] = 0;

    for(int i = 1; i < m; ++i){
        int point = u;
        for(int j = 1; j <= m; ++j){                    //找到与当前点之间边的权值最小的点
            if(point == u && !mark[temp[j]]){
                point = temp[j];
            }
            if(!mark[temp[j]] && dist[point] > dist[temp[j]]){
                point = temp[j];
            }
        }

        mark[point] = true;                              //将这个点收入最小生成树的集合
        sum += dist[point];                              //边的和

        for(int j = 1; j <= m; ++j){                     //更新当前最小生成树集合中的点与不在集合中的点之间边权值最小的边
            if(!mark[temp[j]] && dist[temp[j]] > edge[point][temp[j]]){
                dist[temp[j]] = edge[point][temp[j]];
            }
        }
    }

    return sum;                                            //返回最小生成树边的权值和
}
时间: 2024-10-09 12:08:01

【HDU2489】Minimal Ratio Tree的相关文章

HDU2489 Minimal Ratio Tree 【DFS】+【最小生成树Prim】

Minimal Ratio Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2382    Accepted Submission(s): 709 Problem Description For a tree, which nodes and edges are all weighted, the ratio of it is

HDU-2489 Minimal Ratio Tree(最小生成树)

Minimal Ratio Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4610    Accepted Submission(s): 1466 Problem Description For a tree, which nodes and edges are all weighted, the ratio of it is

hdu 2489 Minimal Ratio Tree(dfs枚举 + 最小生成树)~~~

题目: 链接:点击打开链接 题意: 输入n个点,要求选m个点满足连接m个点的m-1条边权值和sum与点的权值和ans使得sum/ans最小,并输出所选的m个点,如果有多种情况就选第一个点最小的,如果第一个点也相同就选第二个点最小的........ 思路: 求一个图中的一颗子树,使得Sum(edge weight)/Sum(point weight)最小~ 数据量小,暴力枚举~~~~~dfs暴力枚举C(M,N)种情况. 枚举出这M个点之后,Sum(point weight)固定,进行prim或者K

hdu 2489 Minimal Ratio Tree DFS枚举点+最小生成树 属于中等偏上题 ,Double比较大小的时候注意精度问题

Minimal Ratio Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2835    Accepted Submission(s): 841 Problem Description For a tree, which nodes and edges are all weighted, the ratio of it is

AC日记——【模板】Link Cut Tree 洛谷 P3690

[模板]Link Cut Tree 思路: LCT模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 300005 int n,m,val[maxn]; int top,ch[maxn][2],f[maxn],xr[maxn],q[maxn],rev[maxn]; inline void in(int &now) { int if_z=1;now=0; char Cget=getchar(); while

HDU 2489 Minimal Ratio Tree (dfs+Prim最小生成树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2489 Problem Description 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

【leetcode】Construct Binary Tree from Preorder and Inorder Traversal

问题: 给定二叉树的前序和中序遍历,重构这课二叉树. 分析: 前序.中序.后序都是针对于根结点而言,所以又叫作先根.中根.后根(当然不是高跟). 前序:根  左 右 中序:左  根 右 对二叉树,我们将其进行投影,就会发现个有趣的事: 发现投影后的顺序,恰好是中序遍历的顺序,这也就是为什么在构造二叉树的时候,一定需要知道中序遍历,因为中序遍历决定了结点间的相对左右位置关系.所以,对一串有序的数组,我们可以来构建二叉有序数,并通过中序遍历,就可以得到这个有序的数组. 既然中序遍历可以通过根结点将序

HDU 2489 Minimal Ratio Tree (DFS枚举+最小生成树Prim)

Problem Description 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 su

【LeetCode】103. Binary Tree Zigzag Level Order Traversal 解题报告

转载请注明出处:http://blog.csdn.net/crazy1235/article/details/51524241 Subject 出处:https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/ Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to ri