「NOI2011」道路修建

传送门:>HERE<

题意:给出一棵树(带权),答案为每条边的权值乘以两边节点数之差的和。

解题思路:

  Dfs就好了,维护一下子树大小。

  这题做得真是心惊胆战……不知道为什么70分WA了许多次,最后把cmath里的abs函数改成algorithm里的或是手打的就AC了…………

  教训:永远手打Abs,不差这三四行。

Code

/*By QiXingzhi*/
#include <cstdio>
#include <queue>
#define  r  read()
#define  Max(a,b)  (((a)>(b)) ? (a) : (b))
#define  Min(a,b)  (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
#define int ll
const int N = 2000010;
const int INF = 1061109567;
inline int read(){
    int x = 0; int w = 1; register int c = getchar();
    while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
    if(c == '-') w = -1, c = getchar();
    while(c >= '0' && c <= '9') x = (x << 3) +(x << 1) + c - '0', c = getchar();
    return x * w;
}
struct Edge{
    int to, cost;
};
int n,x,y,z,ans;
vector <Edge> G[N];
int son[N];
inline void AddEdge(int u, int v, int w){
    Edge e;
    e.to = v, e.cost = w;
    G[u].push_back(e);
}
inline int ABS(int x){
    if(x < 0) return -x;
    return x;
}
void Dfs(int x, int father){
    son[x] = 1;
    int sz = G[x].size();
    for(int i = 0; i < sz; ++i){
        int v = G[x][i].to;
        if(v == father) continue;
        Dfs(v, x);
        son[x] += son[v];
        ans += G[x][i].cost * ABS(son[v] - (n-son[v]));
    }
}
main(){
    //freopen(".in","r",stdin);
    n = r;
    for(int i = 1; i < n; ++i){
        x = r, y = r, z = r;
        AddEdge(x, y, z);
        AddEdge(y, x, z);
    }
    Dfs(1, 0);
    printf("%lld", ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/qixingzhi/p/9343643.html