3727: PA2014 Final Zadanie
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 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
1 2
17 31
Sample Output
31 17
HINT
Source
达哥竟然出的原题... 假设一个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]);
}