P1351 联合权值

Posted tony-double-sky

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1351 联合权值相关的知识,希望对你有一定的参考价值。

P1351 联合权值

题目描述
无向连通图 GG 有 nn 个点, n-1n?1 条边。点从 11 到 nn 依次编号,编号为 ii 的点的权值为 W_iW
i
? ,每条边的长度均为 11 。图上两点 (u, v)(u,v) 的距离定义为 uu 点到 vv 点的最短距离。对于图 GG 上的点对 (u, v)(u,v) ,若它们的距离为 22 ,则它们之间会产生 W_v imes W_uW
v
? ×W
u
? 的联合权值。

请问图 GG 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少?

输入输出格式
输入格式:
第一行包含 1 个整数 n 。

接下来 n-1 行,每行包含 22 个用空格隔开的正整数 u,v u,v ,表示编号为 u和编号为 v 的点之间有边相连。

最后 1 行,包含 n 个正整数,每两个正整数之间用一个空格隔开,其中第 ii 个整数表示图 G 上编号为 ii 的点的权值为 W_i

输出格式:
输出共 11 行,包含 22 个整数,之间用一个空格隔开,依次为图 GG 上联合权值的最大值和所有联合权值之和。由于所有联合权值之和可能很大,输出它时要对 10007 取余。


这题思维还不错。首先我们可以想到一个很浅显的算法:dfs每一个点,到第二层是累加(sum),更新(max),复杂度(O(n^{2})),得到(60pnts)

好了现在继续分析:因为这是一棵树,对于每一个点,它当作“桥梁”时,连接了若干个点,对于连接的任意两点,他们能构成联合权值

很显然依据贪心,我们可以在线性时间内求出最大值和第二大值,他们相乘即为这个桥梁能产生的最大联合权值

好的,最大联合权值解决了,现在我们解决联合权值之和

对于某一个节点(我们把它叫做(1),这个“桥梁”连接的所有点编号为(1 - n)),他产生的权值之和为:

(A[1] = w[1] * w[2] + w[1] * w[3]+ ... + w[1] * w[n])

( = w[1] * sum_{i = 1} ^ {n}w[i],i otin 1)

( = (sum_{i = 1} ^ {n}w[i] * w[1] ) - w[1] ^ {2})

所以这一桥梁所有点产生的联合权值为:

(ans =(sum_{i = 1}^{n}w[i])^{2} - sum_{i = 1}^{n}w[i]^{2})

这题还要培养看清楚题的好习惯啊,题目上说了,只有联合权值之和要取模

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
typedef long long LL;
using namespace std;
int RD(){
    int out = 0,flag = 1;char c = getchar();
    while(c < ‘0‘ || c >‘9‘){if(c == ‘-‘)flag = -1;c = getchar();}
    while(c >= ‘0‘ && c <= ‘9‘){out = out * 10 + c - ‘0‘;c = getchar();}
    return flag * out;
    }
const int Maxn = 1000019,INF = 1e9, M = 10007;
int head[Maxn],nume = 1;
struct Node{
    int v,dis,nxt;
    }E[Maxn << 3];
void add(int u,int v,int dis){
    E[++nume].nxt = head[u];
    E[nume].v = v;
    E[nume].dis = dis;
    head[u] = nume;
    }
int num,w[Maxn];
LL ans,sum;
void find(int u){
    int Max = 0,Maxx = 0;
    LL tot = 0;
    for(int i = head[u];i;i = E[i].nxt){
        int v = E[i].v;
        tot = (tot + w[v]) % M;
        if(w[v] >= Maxx)Max = Maxx,Maxx = w[v];
        else if(w[v] > Max)Max = w[v];
        }
    ans = max(ans,Maxx * Max * 1ll);
    tot = tot * tot % M;
    for(int i = head[u];i;i = E[i].nxt){
        int v = E[i].v;
        tot -= (w[v] * w[v]) % M;
        }
    sum = (sum + tot) % M;
    }
int main(){
    num = RD();
    for(int i = 1;i <= num - 1;i++){
        int u = RD(),v = RD();
        add(u,v,1),add(v,u,1);
        }
    for(int i = 1;i <= num;i++)w[i] = RD();
    for(int i = 1;i <= num;i++)find(i);
    printf("%lld %lld
",ans,(sum + M) % M);
    return 0;
    }










以上是关于P1351 联合权值的主要内容,如果未能解决你的问题,请参考以下文章

P1351 联合权值

P1351 联合权值

P1351 联合权值

P1351 联合权值

P1351 联合权值

P1351 联合权值