单
来源:互联网 发布:lastindexof的用法 js 编辑:程序博客网 时间:2024/04/18 02:37
问题 B: 单
时间限制: 2 Sec 内存限制: 512 MB题目描述
单车联通大街小巷.这就是出题人没有写题目背景的原因.
对于一棵树,认为每条边长度为1,每个点有一个权值a[i].dis(u,v)为点u到v的最短路径的边数.dis(u,u)=0.对每个点求出一个重要程度.点x的重要程度b[x]定义为其他点到这个点的距离乘上对应的点权再求和.即:b[x]=a[1]*dis(1,x)+a[2]*dis(2,x)+....+a[n]*dis(n,x)
现在有很多树和对应的a数组,并求出了b数组.不幸的是,记录变得模糊不清了.幸运的是,树的形态完好地保存了下来,a数组和b数组至少有一个是完好无损的,但另一个数组完全看不清了.
希望你求出受损的数组.多组数据.
输入
第一行输入一个T,表示数据组数。接下来T组数据。
每组数据的第1行1个整数n表示树的点数.节点从1到n编号.
接下来n-1行每行两个整数u,v表示u和v之间有一条边.
接下来一行一个整数t,表示接下来数组的类型。
t=0则下一行是a数组,t=1则下一行是b数组。
接下来一行n个整数,表示保存完好的那个数组,第i个数表示a[i]或b[i]。
输出
T行,每组数据输出一行表示对应的a数组或b数组,数组的相邻元素用一个空格隔开。忽略行末空格和行尾回车.
样例输入
221 2117 3121 2031 17
样例输出
31 1717 31
提示
对于100%的数据,T=5, 2<=n<=100000,1<=u,v<=n,保证给出的n-1条边形成一棵树
对于100%的数据,t=0或t=1,1<=a[i]<=100,1<=b[i]<=10^9,t=1时保证给出的b数组对应唯一的一个a数组。
对于100%的数据,单个输入文件不会包含超过2000000个整数,这段话可以理解为,你不必考虑输入输出对程序运行时间的影响。
对于100%的数据,保证答案不会超过int能表示的范围
接下来的表格中描述了每个测试点的具体特征。每个测试点的5组数据均符合表格中对应的特征。
a->b:sbb[i]=mdd-sb[i];->(mdd=所有ans值和 sb[i]=以i为根的子树ans值和 sbb[i]->i与f[i] b[]之差)
b->a:b[x]-b[f[x]]=(sum-sum[x])-sum[x];
b[1]=∑sum[i] i!=root-> i=(2~n);
把(无根 x!=1)∑b[x]-b[f[x]]=(n-1)sum-∑2*sum[x]; (1)
b[1]=∑sum[i];(2)
得 sum 从下往上推 a[1]=sum-a[x];x=(2~n);
#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<queue>#include<map>#include<cstdlib>#include<algorithm>#define V 300000#define mod 1000000007#define LL long longusing namespace std;int n,m,tt,f[V];LL dis[V],sb[V],ans[V],dep[V],mdd,sbb[V],son[V],s1[V],ass[V]; //mb[V],struct da{ int to,next; }Edge[V];int head[V],tot,md[V];inline void add(int x,int y){ Edge[tot].to=y; Edge[tot].next=head[x]; head[x]=tot++;} void dfs1(int x){ int v; sb[x]=md[x]; for(int i=head[x];i!=-1;i=Edge[i].next) { v=Edge[i].to; if(v!=f[x]) { f[v]=x; dep[v]=dep[x]+1; dfs1(v); sb[x]+=sb[v]; } } }inline void init(){ mdd=tot=0; memset(head,-1,sizeof(head)); memset(md,0,sizeof(md)); memset(ans,0,sizeof(ans)); memset(dep,0,sizeof(dep)); memset(f,0,sizeof(f)); memset(sb,0,sizeof(sb)); memset(ass,0,sizeof(ass)); memset(son,0,sizeof(son)); memset(s1,0,sizeof(s1));} queue<int>Q;inline void bfs1() { int v,vv; for(int i=head[1];i!=-1;i=Edge[i].next) { v=Edge[i].to; ans[v]=ans[1]-sb[v]+sbb[v]; Q.push(v); } while(!Q.empty()) { v=Q.front();Q.pop(); for(int i=head[v];i!=-1;i=Edge[i].next){ vv=Edge[i].to; if(vv!=f[v]) { ans[vv]=ans[v]-sb[vv]+sbb[vv]; Q.push(vv); } } }}void dfs(int x){ int v; //sb[x]=md[x]; if(x!=1)ans[x]=md[x]-md[f[x]]; for(int i=head[x];i!=-1;i=Edge[i].next) { v=Edge[i].to; if(v!=f[x]) { f[v]=x; dep[v]=dep[x]+1; son[x]++; dfs(v); } } if(!son[x])Q.push(x); }void bfs(){ int v,vv,mbb; while(!Q.empty()) { v=Q.front(); Q.pop(); if(v==1)continue; mbb=0; for(int i=head[v];i!=-1;i=Edge[i].next) { vv=Edge[i].to; if(v!=f[v]){ mbb+=2*sb[vv]; sb[v]+=sb[vv]; } } ans[v]-=mdd; ans[v]+=mbb; ass[v]=-ans[v]/2; sb[v]+=ass[v]; s1[f[v]]++; if(s1[f[v]]==son[f[v]])Q.push(f[v]); }}void pd(){ for(int i=1;i<=n;i++) cout<<ass[i]<<" "; cout<<endl;}inline int haha(){ // freopen("in.txt","r",stdin);freopen("out.txt","w",stdout); //freopen("add.in","r",stdin);freopen("add.out","w",stdout); int t,x,y,v; cin>>t; while(t--) { init(); cin>>n;for(int i=1;i<n;i++){ cin>>x>>y; add(x,y); add(y,x); } cin>>tt;if(!tt){ for(int i=1;i<=n;i++) { scanf("%d",&md[i]); mdd+=md[i]; } dfs1(1); for(int i=1;i<=n;i++) { sbb[i]=mdd-sb[i]; ans[1]+=dep[i]*md[i]; } bfs1(); for(int i=1;i<=n;i++) printf("%d ",ans[i]); cout<<endl; } else { for(int i=1;i<=n;i++) scanf("%d",&md[i]); dfs(1); for(int i=2;i<=n;i++) mdd+=ans[i]; mdd+=md[1]*2; mdd/=n-1; bfs(); for(int i=2;i<=n;i++) mdd-=ass[i]; ass[1]=mdd; pd(); } } //while(1); return 0; }int gg=haha();int main(){;}
- 单
- 单生产者,单消费者
- 单生产者 单消费者
- 单件
- 配置单
- 话单
- 装货单
- 读书单
- 单态
- 录单
- 单例
- 单态
- 单例
- 单态
- 单件
- 单反
- 单播
- 核销单
- linux的内核之内存屏障
- CSS学习1
- linux c 获取文件大小
- 平滑升级Nginx,添加ssl以及echo模块
- java ByteBuffer类的重点
- 单
- js 根据已知的时间,判断是否是今天,明天,昨天,后天
- Web与OC交互---WKWebView
- centos用户和用户组管理
- mongodb和springMVC整合
- 【CSP201312-3】最大的矩形
- 安卓intent详解
- 数据分析书单
- 【poj3320】Jessica's Reading Problem(尺取)