zoukankan      html  css  js  c++  java
  • 51nod 配对(求树的重心)

    传送门:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1737

    给出一棵n个点的树,将这n个点两两配对,求所有可行的方案中配对两点间的距离的总和最大为多少。
    Input
    一个数n(1<=n<=100,000,n保证为偶数)
    接下来n-1行每行三个数x,y,z表示有一条长度为z的边连接x和y(0<=z<=1,000,000,000)
    Output
    一个数表示答案
    Input示例
    6
    1 2 1
    1 3 1
    1 4 1
    3 5 1
    4 6 1
    Output示例
    7
    //配对方案为(1,2)(3,4)(5,6)

    这题一开始完全没思路,后来在评论中看到有人说是求树的重心再到其他点的距离和,就去查了下树的重心的定义——找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心。对于这题,配对的两点的路径一定要经过重心,这样才能保证距离最大,而如果任意两点都经过重心,他们的总距离一定是重心到其他点的距离和。这个模拟一下就能知道了。通过这题顺带学习一下树的重心。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <string>
    #include <stack>
    #include <map>
    #include <set>
    #include <bitset>
    #define X first
    #define Y second
    #define clr(u,v); memset(u,v,sizeof(u));
    #define in() freopen("data","r",stdin);
    #define out() freopen("ans","w",stdout);
    #define Clear(Q); while (!Q.empty()) Q.pop();
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const int maxn = 1e5 + 10;
    const int INF = 0x3f3f3f3f;
    struct Edge
    {
        int v, to;
        ll w;
    } E[2*maxn];
    int head[maxn], cnt, n, sz, pos;
    int vis[maxn], sum[maxn];
    ll dis[maxn];
    ll ans = 0;
    void init()
    {
        sz = INF;
        clr(head, -1);
        clr(sum, 0);
        clr(dis, 0);
        cnt = 0;
        ans = 0;
    }
    
    void addedge(int v, int u, ll w)
    {
        E[cnt].v = u, E[cnt].w = w, E[cnt].to = head[v];
        head[v] = cnt++;
    }
    
    void dfs(int cur)//求树的重心
    {
        vis[cur] = 1;
        int temp = 0;
        for (int i = head[cur]; ~i; i = E[i].to)
        {
            int v = E[i].v;
            if (vis[v]) continue;
            dfs(v);
            temp = max(temp, sum[v] + 1);//求最大子树节点数
            sum[cur] += sum[v] + 1;
        }
        temp = max(temp, n - sum[cur] - 1);//无向树还要考虑上半部分
        if (temp < sz)
        {
            sz = temp;
            pos = cur;
        }
    }
    
    void solve(int cur)//算距离
    {
        vis[cur] = 1;
        for (int i = head[cur]; ~i; i = E[i].to)
        {
            int v = E[i].v;
            if (vis[v]) continue;
            dis[v] = dis[cur] + E[i].w;
            ans += dis[v];
            solve(v);
        }
    }
    
    int main()
    {
        init();
        int v, u;
        ll w;
        scanf("%d", &n);
        for (int i = 1; i < n; i++)
        {
            scanf("%d%d%I64d", &v, &u, &w);
            addedge(v, u, w), addedge(u, v, w);
        }
        dfs(1);
        clr(vis, 0);
        //cout << sz << " " << pos << endl;
        solve(pos);
        cout << ans << endl;
        return 0;
    }
  • 相关阅读:
    JAVA常见面试题之Forward和Redirect的区别
    [转载]vm文件
    [转载]vm文件
    [转载]心灵丨愿你早一点发现,你才是自己最重要的粉丝
    [转载]心灵丨愿你早一点发现,你才是自己最重要的粉丝
    iBatis整理——Spring环境下批处理实现
    iBatis整理——Spring环境下批处理实现
    SAP HANA 三大特点
    在解决方案中搜索 文件的位置
    我这边测了一下,发现#后面参数变化浏览器不会刷新,但是#一旦去掉就会刷新了,你那边的url拼的时候能不能在没参数的时候#也拼在里面,这样应该就OK了
  • 原文地址:https://www.cnblogs.com/scaugsh/p/6349836.html
Copyright © 2011-2022 走看看