联合权值

联合权值

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;
}
全部评论

相关推荐

Yushuu:你的确很厉害,但是有一个小问题:谁问你了?我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了😆
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务