• P1268 树的重量【构造】


    题目描述

    树可以用来表示物种之间的进化关系。一棵“进化树”是一个带边权的树,其叶节点表示一个物种,两个叶节点之间的距离表示两个物种的差异。现在,一个重要的问题是,根据物种之间的距离,重构相应的“进化树”。

    令N={1..n},用一个N上的矩阵M来定义树T。其中,矩阵M满足:对于任意的i,j,k,有M[i,j] + M[j,k] >= M[i,k]。树T满足:

    1.叶节点属于集合N;

    2.边权均为非负整数;

    3.dT(i,j)=M[i,j],其中dT(i,j)表示树上i到j的最短路径长度。

    如下图,矩阵M描述了一棵树。

    树的重量是指树上所有边权之和。对于任意给出的合法矩阵M,它所能表示树的重量是惟一确定的,不可能找到两棵不同重量的树,它们都符合矩阵M。你的任务就是,根据给出的矩阵M,计算M所表示树的重量。下图是上面给出的矩阵M所能表示的一棵树,这棵树的总重量为15。

    输入格式

    输入数据包含若干组数据。每组数据的第一行是一个整数n(2<n<30)。其后n-1行,给出的是矩阵M的一个上三角(不包含对角线),矩阵中所有元素是不超过100的非负整数。输入数据保证合法。

    输入数据以n=0结尾。

    输出格式

    对于每组输入,输出一行,一个整数,表示树的重量。

    输入输出样例

    输入 #1
    5
    5 9 12 8
    8 11 7
    5 1
    4
    4
    15 36 60
    31 55
    36
    0
    
    输出 #1
    15
    71

    和Three Paths on a tree类似地构造一个树上最短路的式子
    把整张图看作一张AOE网
    通过这张网来建立一棵树,具体实现操作是:
    1、把一个为入树的点入树
    2、在已经入树的它的邻接点中遍历来更新把这个点入树的最小花费。

    显然此时花费是 (dis[i][k] + dis[j][k] - dis[i][j]) / 2;

    3、树的总重量加上把这个点入树的最小花费

    CODE
     1 #include <bits/stdc++.h>
     2 #define dbg(x) cout << #x << "=" << x << endl
     3 #define eps 1e-8
     4 #define pi acos(-1.0)
     5 
     6 using namespace std;
     7 typedef long long LL;
     8 
     9 template<class T>inline void read(T &res)
    10 {
    11     char c;T flag=1;
    12     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    13     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
    14 }
    15 
    16 namespace _buff {
    17     const size_t BUFF = 1 << 19;
    18     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
    19     char getc() {
    20         if (ib == ie) {
    21             ib = ibuf;
    22             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
    23         }
    24         return ib == ie ? -1 : *ib++;
    25     }
    26 }
    27 
    28 int qread() {
    29     using namespace _buff;
    30     int ret = 0;
    31     bool pos = true;
    32     char c = getc();
    33     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
    34         assert(~c);
    35     }
    36     if (c == '-') {
    37         pos = false;
    38         c = getc();
    39     }
    40     for (; c >= '0' && c <= '9'; c = getc()) {
    41         ret = (ret << 3) + (ret << 1) + (c ^ 48);
    42     }
    43     return pos ? ret : -ret;
    44 }
    45 
    46 const int maxn = 107;
    47 
    48 int dis[maxn][maxn];
    49 int n;
    50 
    51 int main()
    52 {
    53     while(scanf("%d",&n) && n) {
    54         memset(dis, 0, sizeof(dis));
    55         for ( int i = 1; i <= n; ++i ) {
    56             for ( int j = i+1; j <= n; ++j ) {
    57                 read(dis[i][j]);
    58                 dis[j][i] = dis[i][j];
    59             }
    60         }
    61         int weight = 0;
    62         int v = 1;
    63         for ( int i = 1; i <= n; ++i ) {
    64             int cost = 0x3f3f3f3f;
    65             for ( int j = 1; j < i; ++j ) {
    66                 int temp = dis[i][v] + dis[i][j] - dis[v][j];
    67                 cost = min(cost, temp / 2);
    68                 //dbg(cost);
    69             }
    70             if(cost != 0x3f3f3f3f)
    71                 weight += cost;
    72         }
    73         cout << weight << endl;
    74     }
    75     return 0;
    76 }
    View Code
    
    
    
    
    
  • 相关阅读:
    昨天一个人KTV啦 哈哈....
    久违的大雪终于来了
    我心目中的英雄李连杰
    今天终于可以回家了
    ajax 笔记不用刷新实现数据的分页显示 2 (下)
    学Linux可不知道怎么入手呀
    在web.config里配制连接Access数据库字符串
    昨天头请我们吃饭
    PDA程序读取xml文件的想法
    关于layui踩过的坑
  • 原文地址:https://www.cnblogs.com/orangeko/p/12336209.html
Copyright © 2020-2023  润新知