BNUOJ 4112 奶牛大集会

    http://acm.cist.bnu.edu.cn/contest/problem_show.php?pid=4212

    这道题挺不错的,之前一次比赛中没过,看了解题报告也不知道啥意思,这几天看了树的知识,也就把这题想了出来。

    1、将树看成以1为根的一棵有根树。

    2、用一个sum[maxn]记录该节点以下的牛的个数。

    3、用一个a[maxn]表示该节点为聚会地点时,奶牛们的不方便程度。

    那么有:

    sum[ i ] = val[i] + sum[ son(i) ];

    a[ i ] += a[ son(i) ] + sum[ son(i) ] * w;

    a[ i ] += (total - sum[ i ]) * w + (a[ father(i) ] - a[ i ] - sum[v] * w);

    其中val[i] 表示该点的牛数目,total 表示总的牛数量,w 表示 father(i) 到i点的距离。

    这样,进行两次DFS,第一次DFS则要得到sum[]的值还有以这棵树来看时候的a[]值,这个时候a[]值仅为a[ son(i) ] + sum[ son(i) ] * w,不算包括父亲在内的另一部分子树的不满意度,第二次DFS则要计算a[],需要两次DFS的原因是,必须要用一个节点的不满意度已经求出,才能求出这个点以下的节点的不满意度。

    题目超int ,直接用long long 表示了。

BNUOJ 4112
1 #include <cstdio>
2 #include <iostream>
3  using namespace std;
4
5 const int maxn = 1000000 + 1;
6 typedef long long LL;
7
8 LL val[maxn], n, visit[maxn], sum[maxn], a[maxn], total, e_num;
9 struct node
10 {
11 LL v, w;
12 node* next;
13 } *adj[maxn], edge[maxn];
14
15 void add_edge(LL u, LL v, LL w)
16 {
17 node* ptr = &edge[ e_num ++ ];
18 ptr -> v = v;
19 ptr -> w = w;
20 ptr -> next = adj[u];
21 adj[u] = ptr;
22 }
23
24 void DFS(LL u)
25 {
26 visit[u] = 1;
27 for(node* ptr = adj[u]; ptr; ptr = ptr -> next)
28 {
29 LL v = ptr -> v;
30 LL w = ptr -> w;
31 if(visit[v])
32 continue;
33 DFS(v);
34 sum[u] += sum[v];
35 a[u] += (a[v] + sum[v] * w);
36 }
37 sum[u] += val[u];
38 }
39
40 void GET(LL u)
41 {
42 visit[u] = 1;
43 for(node* ptr = adj[u]; ptr; ptr = ptr -> next)
44 {
45 LL v = ptr -> v;
46 LL w = ptr -> w;
47 if(visit[v])
48 continue;
49 a[v] += (total - sum[v]) * w + (a[u] - a[v] - sum[v] * w);
50 GET(v);
51 }
52 }
53
54 void solve()
55 {
56 DFS(1);
57 memset(visit , 0 , sizeof(visit));
58 GET(1);
59 LL mn = a[1];
60 for(LL i=1; i <= n; i++)
61 {
62 mn = min(mn , a[i]);
63 }
64 printf("%lld\n", mn);
65 }
66
67 int main()
68 {
69 scanf("%lld", &n);
70 total = e_num = 0;
71 for(LL i=1; i <= n; i++)
72 {
73 scanf("%lld", &val[i]);
74 total += val[i];
75 }
76 LL u , v , w;
77 for(LL i=1; i <= n - 1; i++)
78 {
79 scanf("%lld %lld %lld", &u, &v, &w);
80 add_edge(u, v, w);
81 add_edge(v, u, w);
82 }
83 solve();
84 return 0;
85 }
86

 

posted on 2010-06-01 17:55  xIao.wU 思维磁场  阅读(574)  评论(0编辑  收藏  举报