1 篇文章 0 订阅

问题 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数组,数组的相邻元素用一个空格隔开。忽略行末空格和行尾回车.

样例输入

22	1 21	17 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 long
using 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()
{;}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值