传送门(洛谷)
一道树上操作题
分两种情况操作,设当前节点为 u u u,儿子为 v v v,父亲为 f a fa fa
- v v v与 f a fa fa可以组成一对联合权值,也就是一条链的情况
- v v v与 u u u的其他儿子可以组成一对联合权值
用一个 t o t tot tot数组存储 u u u除去 v v v的其他儿子的权值,再用乘法分配律乘起来就行,即 a n s 2 = t o t ∗ w [ v ] ans2=tot*w[v] ans2=tot∗w[v]。
Code
#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define MOD 10007
using namespace std;
const int maxn=200000+10;
int n,cnt=0;
int head[maxn],w[maxn];
int ans1,ans2;
struct node{
int v,nex;
}e[maxn<<1];
template <class t> void read(t &x)
{
x=0;int f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
x*=f;
}
void add(int u,int v)
{
e[++cnt].v=v;
e[cnt].nex=head[u];
head[u]=cnt;
}
void readdata()
{
memset(head,-1,sizeof(head));
read(n);
rep(i,1,n-1)
{
int a,b;
read(a),read(b);
add(a,b);
add(b,a);
}
}
void dfs(int u,int fa)
{
int maxx=0,tot=0;
for(int i=head[u];~i;i=e[i].nex)
{
int v=e[i].v;
if(v==fa) continue;
/* if(fa)
{
int sum=w[fa]*w[v];
ans2+=sum;
ans2=ans2%MOD;
ans1=max(ans1,sum);
}处理一条链,也可以写成注释掉的部分*/
ans2+=w[fa]*w[v]+tot*w[v];//加上爷爷节点和兄弟节点
ans2%=MOD;maxx%=MOD;
ans1=max(ans1,w[fa]*w[v]);//ans1分别与爷爷节点和兄弟节点比较
if(maxx!=0) ans1=max(ans1,maxx*w[v]);
maxx=max(maxx,w[v]);
tot+=w[v];//处理树,即处理兄弟节点
tot=tot%MOD;
dfs(v,u);
}
}
void work()
{
rep(i,1,n) read(w[i]);
dfs(1,0);
ans2=(ans2*2)%MOD;
printf("%d %d",ans1,ans2);
}
int main()
{
freopen("input.txt","r",stdin);
readdata();
work();
return 0;
}