联合权值
程序员文章站
2022-05-22 14:35:08
...
读完题我们会发现此题有树结构。
我们以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;
}
上一篇: 图论模板