无向连通图 G 有 n 个点,n-1 条边。点从 1 到 n 依次编号,编号为 i 的点的权值为 Wi,每条边的长度均为 1。图上两点(u, v)的距离定义为 u 点到 v 点的最短距离。对于图 G 上的点对(u, v),若它们的距离为 2,则它们之间会产生Wu*Wv的联合权值。
请问图 G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少?
题解:树形dp;
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include<algorithm> #include<iomanip> #include<map> #include<set> #include<vector> #include<ctime> #include<cmath> #define LL long long using namespace std; #define LL long long #define up(i,j,n) for(int i=(j);(i)<=(n);(i)++) #define max(x,y) ((x)<(y)?(y):(x)) #define min(x,y) ((x)<(y)?(x):(y)) #define FILE "1" const int maxn=202000,mod=10007; int read(){ int x=0;bool flag=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')flag=1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return flag?-x:x; } int n; struct node{ int y,next; }e[maxn<<1]; int linkk[maxn],len=0,w[maxn],maxx[maxn]; int Max=0,Sum=0; void insert(int x,int y){ e[++len].y=y; e[len].next=linkk[x]; linkk[x]=len; } void init(){ n=read(); int x,y; up(i,2,n){ x=read(),y=read(); insert(x,y);insert(y,x); } up(i,1,n)w[i]=read(); } int q[maxn],tail,head=0,fa[maxn],siz[maxn],ans[maxn],ru[maxn]; void bfs(){ head=tail=0; q[++tail]=1;int x; while(++head<=tail){ x=q[head]; for(int i=linkk[x];i;i=e[i].next){ if(e[i].y==fa[x])continue; ru[x]++; fa[e[i].y]=x; q[++tail]=e[i].y; } } tail=0,head=0; up(i,1,n)if(!ru[i])q[++tail]=i; while(++head<=tail){ x=q[head]; ans[x]=(ans[x]+w[fa[x]]*siz[x])%mod; Sum+=ans[x]; if(--ru[fa[x]]==0)q[++tail]=fa[x]; ans[fa[x]]=(ans[fa[x]]+siz[fa[x]]*w[x])%mod; siz[fa[x]]=(siz[fa[x]]+w[x])%mod; Sum=(Sum+ans[x])%mod; if(w[x]*maxx[fa[x]]>Max)Max=w[x]*maxx[fa[x]]; if(w[fa[x]]*maxx[x]>Max)Max=w[fa[x]]*maxx[x]; if(w[x]>maxx[fa[x]])maxx[fa[x]]=w[x]; } cout<<Max<<" "<<Sum<<endl; } int main(){ freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); init(); bfs(); }