Abandoned country HDU - 5723

Posted gredcomet

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Abandoned country HDU - 5723相关的知识,希望对你有一定的参考价值。

题目链接
题意:给你一棵树,让你求每个点之间的距离的最短之和
题解:看到最短之和,想到最小生成树,且每条边权不同,最小生成树唯一,就转换问题为,求一棵树上每个点到所有点的距离之和,这就是树形dp,先对一个点跑dfs,求出该点到所有点的距离之和,统计每个点的子树个数,并假设该点为根,再跑一次dfs统计(dp)
(dp_i)为第i个节点到每个点的路径之和,假设(j)是他的子节点,容易知,有(siz_j)个节点到(j)的距离比到(i)少权值(w),有(n-siz_j)个节点到(j)的距离比到(i)多权值(w)
那就可以得到关系式:(dp_j = dp_i - w*siz_j + w*(n-siz_j) = dp_i - w*(n-2*siz_j))
因为有1e6条边,用prim要用链式前向星存图即可

#include<bits/stdc++.h>
using namespace std;
#define ms(x,y) memset(x, y, sizeof(x))
#define lowbit(x) ((x)&(-x))
typedef long long LL;
typedef pair<int,int> pii;


const int maxn = 1e5+7;
const int maxm = 1e6+7;
int head1[maxm<<1], head2[maxn<<1], edgecnt1, edgecnt2, siz[maxn], n, m;
bool vis[maxn];
LL dp[maxn];
struct Node {
    int u, v, w, nex;
} edges1[maxm<<1], edges2[maxn<<1];

struct edge {
    int u, v, w;
    edge(int _u, int _v, int _w):u(_u), v(_v), w(_w){}
    bool operator < (const edge a) const {
        return a.w < w;
    }
};

void addedge1(int u, int v, int w) {
    edges1[edgecnt1] = Node{u, v, w, head1[u]};
    head1[u] = edgecnt1++;
    edges1[edgecnt1] = Node{v, u, w, head1[v]};
    head1[v] = edgecnt1++;
}

void addedge2(int u, int v, int w) {
    edges2[edgecnt2] = Node{u, v, w, head2[u]};
    head2[u] = edgecnt2++;
    edges2[edgecnt2] = Node{v, u, w, head2[v]};
    head2[v] = edgecnt2++;
}

void init() {
    ms(head1, -1), ms(head2, -1), ms(vis, false);
    edgecnt1 = edgecnt2 = 0;
    dp[1] = 0;
}

LL prim() {
    LL minsum = 0;
    priority_queue<edge> q;
    vis[1] = true;
    for(int i = head1[1]; i != -1; i = edges1[i].nex) {
        int v = edges1[i].v, w = edges1[i].w;
        q.push(edge(1, v, w));
    }
    while(!q.empty()) {
        auto now = q.top();
        q.pop();
        if(vis[now.v]) continue;
        vis[now.v] = true;
        minsum += now.w;
        int u = now.v;
        addedge2(now.u, u, now.w);
        for(int i = head1[u]; i != -1; i = edges1[i].nex) {
            int v = edges1[i].v, w = edges1[i].w;
            if(vis[v]) continue;
            q.push(edge{u, v, w});
        }
    }
    return minsum;
}

void dfs1(int u, int fa, LL val, LL &ans) {
    siz[u] = 1;
    ans += val;
    for(int i = head2[u]; i != -1; i = edges2[i].nex) {
        int v = edges2[i].v;
        if(v == fa) continue;
        dfs1(v, u, val+edges2[i].w, ans);
        siz[u] += siz[v];
    }
}

void dfs2(int u, int fa, LL &ans) {
    for(int i = head2[u]; i != -1; i = edges2[i].nex) {
        int v = edges2[i].v, w = edges2[i].w;
        if(v == fa) continue;
        dp[v] = dp[u] + 1LL*w*(n-2*siz[v]);
        ans += dp[v];
        dfs2(v, u, ans);
    }
}

void run_case() {
    init();
    cin >> n >> m;
    for(int i = 0; i < m; ++i) {
        int u, v, w;
        cin >> u >> v >> w;
        addedge1(u, v, w);
    }
    LL ans1 = prim(); 
    dfs1(1, 0, 0, dp[1]);
    LL ans2 = dp[1];
    dfs2(1, 0, ans2);
    cout << ans1 << " " << (double)ans2/n/(n-1) << "
";
}

int main() {
    ios::sync_with_stdio(false), cin.tie(0);
    cout.flags(ios::fixed);cout.precision(2);
    int t; cin >> t;
    while(t--)
    run_case();
    cout.flush();
    return 0;
}

以上是关于Abandoned country HDU - 5723的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5723 Abandoned country(最小生成树+边两边点数)

瞎搞 HDU 3101 The Heart of the Country

Codeforces Round #418 A--An abandoned sentiment from past

(状压dp)ABC 067 F : Mole and Abandoned Mine

AT2657 Mole and Abandoned Mine

tomcat重启警告:Abandoned connection cleanup thread 服务器宕机解决方案