[BZOJ]3727 Final Zadanie 公式推导

来源:互联网 发布:程序员保密协议 外包 编辑:程序博客网 时间:2024/06/05 10:51

3727: PA2014 Final Zadanie

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 319  Solved: 138
[Submit][Status][Discuss]

Description

吉丽YY了一道神题,题面是这样的:
“一棵n个点的树,每条边长度为1,第i个结点居住着a[i]个人。假设在i结点举行会议,所有人都从原住址沿着最短路径来到i结点,行走的总路程为b[i]。输出所有b[i]。”
吉丽已经造好了数据,但熊孩子把输入文件中所有a[i]给删掉了。你能帮他恢复吗?

Input

第一行一个整数n(2<=n<=300000)。
接下来n-1行,每行两个整数x,y,表示x和y之间有连边。
接下来一行由空格隔开的n个整数b[i](0<=b[i]<=10^9)。

Output

输出一行由空格隔开的n个整数a[i]。
如果你觉得有多组解就任意输出其中一组。

Sample Input

2
1 2
17 31

Sample Output

31 17

HINT

Source

鸣谢Jcvb

[Submit][Status][Discuss]


HOME Back

达哥竟然出的原题... 假设一个sum[1]推导出所有的a, 再计算与真实的sum[1]之间的差值就可以了.

好吧有点模糊... 自己写的详解具体在这套的第二题 : Click Here 

班上人看见我这个假设法挺懵逼的...尤其是看见第35行的随便假设.... 大胆猜想, 理性推测.

#include<stdio.h>#include<cstring>#define Mercer   register int#define clear(a) memset(a, 0, sizeof(a))const int maxn = 300005;typedef long long dnt;dnt all, punchh, delta;int num, n, t, T, fake, rightt;int h[maxn], a[maxn], b[maxn], sum[maxn], dis[maxn], cnt[maxn];inline const int read(){register int x = 0;register char ch = getchar();while(ch < '0' || ch > '9') ch = getchar();while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();return x;}struct edge{ int nxt, v;}e[maxn * 2];inline void add(int u, int v){e[++num].v = v, e[num].nxt = h[u], h[u] = num;e[++num].v = u, e[num].nxt = h[v], h[v] = num;}void dfss(int u, int fa){a[u] = sum[u];for(int i = h[u]; i; i = e[i].nxt){int v = e[i].v;if(v == fa) continue;sum[v] = (sum[1] - b[v] + b[u]) / 2;dis[v] = dis[u] + 1, dfss(v, u);a[u] -= sum[v];cnt[u]++;}}inline void work(){for(Mercer i = 1; i <= n; ++i) b[i] = read();if((10000000 + b[1] - b[fake]) & 1) sum[1] = 10000001;else sum[1] = 10000000;dfss(1, 1);for(Mercer i = 2; i <= n; ++i) all += (dnt) a[i] * dis[i], punchh += dis[i];delta = (b[1] - all) * 2;for(Mercer i = 2; i <= n; ++i) rightt += (dnt) dis[i] * (1 - cnt[i]);delta /= rightt, sum[1] += delta;dfss(1, 1);}int main(){n = read();for(Mercer i = 1; i < n; ++i){int u = read(), v = read();add(u, v);if(u == 1) fake = v;if(v == 1) fake = u;}work();for(Mercer i = 1; i < n; ++i) printf("%d ", a[i]);printf("%d\n", a[n]);}


原创粉丝点击