zoukankan      html  css  js  c++  java
  • Luogu1268 树的重量

    题中给出了邻接矩阵,而且 n 比较小,可以先考虑 Floyd 那样的做法

    一些三个点组成的点集他们之间的关系是满足 dst[i][j] = dst[i][k] + dst[k][j]
    这些点的位置关系是可以先确定下来的

    但是有些点之间的距离连出来会不一样,甚至还有些点加不到图中

    考虑加入了图中但是距离不对的点,他们中间一定至少有个中转点
    而在其他点的距离都计算正确的情况下,
    枚举所有点作为中转点后取最小值
    最小值一定是距离不正确的点对中的一个点(设为 k)向上连接的边长
    用这个式子计算:val = (dst[i][j] + dst[j][k] + dst[k][i]) / 2 - dst[i][j]

    简(hu)单(luan)证明一下就是如果最小值不是我们想要的东西的话
    那一定是一个较大的值,而存在较小值一定是较大值是较大值多走了一条/些边
    (自己画一条链计算端点的值随便找几个点试一下就发现了)

     感觉菊花图没法做,像是这样:

    其实这种时候随意找两个点,他们之间的距离是正确的
    再按照上面的计算方式是可以计算的

    具体在实现的时候,发现他可以像 Floyd 差不多写

    只要把他之前加入的都算上求最小值就行,
    顺序讲道理是无所谓的只要把他和其他的都计算一遍就好

    为了方便就从 1 到 n 依次加入了


     代码:

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cctype>
    #include <cstdio>
    using namespace std;
    
    const int MAX_N = 35;
    
    int n, ans;
    int dst[MAX_N][MAX_N];
    
    int main() {
        while (scanf("%d", &n) && n) {
            ans = 0;
            for (int i = 1; i <= n; ++i) {
                for (int j = i + 1; j <= n; ++j) {
                    scanf("%d", &dst[i][j]);
                }
            }
            ans = dst[1][2];
            for (int k = 3; k <= n; ++k) {
                register int cur_ans = 0x3f3f3f3f;
                for (int i = 1; i < k; ++i) {
                    for (int j = i + 1; j < k; ++j) {
                        cur_ans = min(cur_ans,
                                (dst[i][j] + dst[min(j, k)][max(j, k)] +
                                dst[min(i, k)][max(i, k)]) / 2 - dst[i][j]);
                    }
                }
                ans += cur_ans;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    JDK6和JDK7中的substring()方法
    考试结束
    今天之总结
    暂别
    珍惜
    放弃
    我男神
    心态
    稳住,我或许能赢
    还是做好自己吧
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9880854.html
Copyright © 2011-2022 走看看