联合权值
联合权值
https://ac.nowcoder.com/acm/problem/16495
读完题我们会发现此题有树结构。
我们以1为根结点。
假设我们已经做完了x号节点(x可以是叶子节点)的儿子们(y号节点),
我们就在x号节点的tot加上y的tot。
设maxx为与x连边的节点中点权最大值,
每次maxx与y的点权的乘积就可能是最大值。
设sum为与x连边的节点中点权之和,x的tot加上sum与y的点权的乘积,
这样就能不重复的统计所有序点对的联合权值。自己模拟一下就可以知道。
返回最大值(maxx)和tot
#include<cstdio> #include<algorithm> using namespace std; const int p=10007,M=200010; struct bian{int y,gg;}b[M<<1]; struct lol{int tot,maxx;}; int h[M],a[M],len=0; void ins(int x,int y) { b[++len].y=y;b[len].gg=h[x]; h[x]=len; } lol dfs(int x,int fa) { lol ans; int maxx,sum; sum=maxx=a[fa]; ans.tot=ans.maxx=0; for(int i=h[x];i;i=b[i].gg) { int y=b[i].y; if(fa==y)continue; lol k=dfs(y,x); ans.maxx=max(ans.maxx,k.maxx); ans.tot=(ans.tot+k.tot)%p; ans.tot=(ans.tot+sum*a[y]%p)%p; sum=(sum+a[y])%p; ans.maxx=max(maxx*a[y],ans.maxx); maxx=max(a[y],maxx); } return ans; } int main() { int n;scanf("%d",&n); for(int i=1;i<n;i++) { int x,y;scanf("%d %d",&x,&y); if(x>y){x^=y;y^=x;x^=y;}//swap ins(x,y);ins(y,x); } for(int i=1;i<=n;i++)scanf("%d",&a[i]); lol ans=dfs(1,0); printf("%d %d",ans.maxx,(ans.tot<<1)%p); return 0; }