3403 - 联合权值
时间限制 : 1 秒
内存限制 : 128 MB
无向连通图G有n个点,n-1条边。点从1到n依次编号,编号为i的点的权值为Wi ,
每条边的长度均为1。图上两点(u, v)的距离定义为u点到v点的最短距离。对于图G上的点
对(u, v),若它们的距离为2,则它们之间会产生�!×�!的联合权值。
请问图G上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权
值之和是多少
题目输入
输入文件名为link.in。
第一行包含1个整数n。
接下来n-1行,每行包含2个用空格隔开的正整数u、v,表示编号为u和编号为v的点
之间有边相连。
最后1行,包含n个正整数,每两个正整数之间用一个空格隔开,其中第i个整数表示
图G上编号为i的点的权值为Wi
题目输出
输出文件名为link.out。
输出共1行,包含2个整数,之间用一个空格隔开,依次为图G上联合权值的最大值
和所有联合权值之和。由于所有联合权值之和可能很大,输出它时要对10007取余
输入/输出样例
输入格式
5 1 2 2 3 3 4 4 5 1 5 2 3 10
输出格式
20 74
C++解答
#include <cstdio> #define maxn 200005LL #define maxe 400010LL #define ansmod 10007LL //typedef long long ll ; int n ; struct FST{ int to , next ; } e[maxe] ; int tot = 0 , star[maxn] = {0} ; void AddEdge(int u , int v) { tot ++ ; e[tot].to = v ; e[tot].next = star[u] ; star[u] = tot ; } int ans = 0 ; int ans2 = 0 ; int val[maxn] = {0} ;/*每个节点原权值*/ int sum[maxn] = {0} ;/*每个节点的儿子节点权值和*/ int maxx[maxn] = {0} ;/*每个节点中第一大儿子节点权值*/ void dfs(int now , int fa) { int next , p ; for (p=star[now] , next=e[p].to ; p ; p=e[p].next , next=e[p].to) { if (next == fa) continue ; ans += (val[next]*sum[now])%ansmod ; ans %= ansmod ; sum[now] += val[next] ; sum[now] %= ansmod ; if (val[next]*maxx[now] > ans2) ans2 = val[next]*maxx[now] ; if (val[next] > maxx[now]) maxx[now] = val[next] ; dfs(next , now) ; ans += (val[now]*sum[next])%ansmod ; ans %= ansmod ; if (val[now]*maxx[next] > ans2) ans2 = val[now]*maxx[next] ; } } int main() { // freopen("link.in" ,"r",stdin ) ; // freopen("link.out","w",stdout) ; int i , u , v ; scanf("%d", &n ) ; for (i = 1 ; i < n ; i ++ ) { scanf("%d%d", &u , &v ) ; AddEdge(u , v) ; AddEdge(v , u) ; } for (i = 1 ; i <= n ; i ++ ) { scanf("%d", &val[i] ) ; } dfs(1,0) ; printf("%d %d\n", ans2 , (ans*2)%ansmod ) ; fclose(stdin ) ; fclose(stdout) ; return 0 ; }