现在的位置: 首页 > 综合 > 正文

HDU 3899 JLUCPC 树型DP

2017年11月20日 ⁄ 综合 ⁄ 共 2837字 ⁄ 字号 评论关闭

JLUCPC

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1101    Accepted Submission(s): 295

Problem Description
Dr. Skywind and Dr. Walkoncloud are planning to hold the annual JLU Collegiate Programming Contest. The contest was always held in the college of software in the past. However, they changed their minds and decided to find the most
convenient location from all colleges this year.
Each college in JLU is located in one of the N (1 <= N <= 100,000) different locations (labeled as 1 to N) connected by N-1 roads. Any two colleges are reachable to each other. The Contest can be held at any one of these N colleges. Moreover, Road i connects
college A_i and B_i (1 <= A_i <=N; 1 <= B_i <= N) and has length L_i (1 <= L_i <= 1,000). College i has T_i (0 <= T_i <= 1,000) teams participating in the contest.
When choosing the college to hold the Contest, Dr. Skywind wishes to minimize the inconvenience of the chosen location. The inconvenience of choosing college P is the sum of the distance that all teams need to reach college P (i.e., if the distance from college
i to college P is 20, then the travel distance is T_i*20). Please help Dr. Skywind and Dr. Walkoncloud to choose the most convenient location for the contest.
 

Input
There are multiple test cases. For each case, the first line contains a single integer N, indicating the number of colleges. The next N lines describes T_1 to T_n. Then, each of the last N-1 lines will contain 3 integers, namely A_i,
B_i and L_i.
 

Output
For each case, output the minimum inconvenience possible
 

Sample Input
3 1 1 2 1 2 2 2 3 1 4 100 1 1 1 1 2 1 2 3 1 2 4 1
 

Sample Output
4 5
 

Source
2011 Multi-University Training Contest 6 - Host by JLU

题目链接:HDU 3899 JLUCPC

题目大意:n个带权点T[i],n - 1条带权无向边,选定一个点 t 作为终点使得花费 = sum(T[i],dis(i,t))。问如何选择终点使得花费最小。

题目分析:树型DP,dfs预处理出每个点包括其子树的权值和以及以这个点为根节点的这颗子树的花费。然后第二遍dfs不断转移状态,得到以每个点为根节点的整棵树的花费。最后取最小值输出即可。
PS:题目略坑,数据量大,递归会爆栈,不得已用上了扩展神器。。以后有空再来琢磨非递归的好了。。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define min(A, B) ((A) < (B) ? (A) : (B))
#define clear(A, X, SIZE) memset(A, X, sizeof(A[0]) * (SIZE + 1))
using namespace std;
typedef long long ll;
const int maxE = 200005;
const int maxN = 100005;
const ll oo = 1e18;
struct Edge{
    int v, w, n;
    Edge(){}
    Edge(int Var, int Val, int Next):v(Var), w(Val), n(Next){}
};
Edge edge[maxE];
int adj[maxN], cntE;
int T[maxN], siz[maxN];
ll dp[maxN];
int n;
void dfs(int u, int fa){
    siz[u] = T[u];
    for(int i = adj[u]; ~i; i = edge[i].n){
        if(edge[i].v == fa) continue;
        dfs(edge[i].v, u);
        dp[u] += dp[edge[i].v] + (ll)siz[edge[i].v] * edge[i].w;
        siz[u] += siz[edge[i].v];
    }
}
void dfs2(int u, int fa){
    for(int i = adj[u]; ~i; i = edge[i].n){
        if(edge[i].v == fa) continue;
        dp[edge[i].v] = dp[u] - (ll)siz[edge[i].v] * edge[i].w + (ll)(siz[1] - siz[edge[i].v]) * edge[i].w;
        dfs2(edge[i].v, u);
    }
}
void work(){
    int u, v, w;
    clear(adj, -1, n);
    clear(dp, 0, n);
    cntE = 0;
    for(int i = 1; i <= n; ++i) scanf("%d", &T[i]);
    for(int i = 1; i < n; ++i){
        scanf("%d%d%d", &u, &v, &w);
        edge[cntE] = Edge(v, w, adj[u]); adj[u] = cntE++;
        edge[cntE] = Edge(u, w, adj[v]); adj[v] = cntE++;
    }
    dfs(1, 0);
    dfs2(1, 0);
    ll ans = oo;
    for(int i = 1; i <= n; ++i) ans = min(ans, dp[i]);
    printf("%I64d\n", ans);
}
int main(){
    while(~scanf("%d", &n)) work();
    return 0;
}

抱歉!评论已关闭.