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 联合权值的主要内容,如果未能解决你的问题,请参考以下文章