题目描述
无向连通图 GGG 有 nnn 个点,n−1n-1n−1 条边。点从 111 到 nnn 依次编号,编号为 iii 的点的权值为 WiW_iWi?,每条边的长度均为 111。图上两点 (u,v)(u, v)(u,v) 的距离定义为 uuu 点到 vvv 点的最短距离。对于图 GGG 上的点对 (u,v)(u, v)(u,v),若它们的距离为 222,则它们之间会产生Wv×WuW_v \times W_uWv?×Wu? 的联合权值。
请问图 GGG 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少?
输入格式
第一行包含 111 个整数 nnn。
接下来 n−1n-1n−1 行,每行包含 222 个用空格隔开的正整数 u,vu,vu,v,表示编号为 uuu 和编号为 vvv 的点之间有边相连。
最后 111 行,包含 nnn 个正整数,每两个正整数之间用一个空格隔开,其中第 iii 个整数表示图 GGG 上编号为 iii 的点的权值为 WiW_iWi?。
输出格式
输出共 111 行,包含 222 个整数,之间用一个空格隔开,依次为图 GGG 上联合权值的最大值和所有联合权值之和。由于所有联合权值之和可能很大,输出它时要对100071000710007取余。
每个节点,他所连接的各个节点之间的距离都是2,因为一共那个点,所以两层循环相当于nlogn,不会超范围
为了不超,把一个点所连接的所有点和求出来,(k-a[i])*a[i]表示这个点和剩余所有的点的乘积的和,把每个点都如此处理,再把所得结果相加
以自己亲身血泪经验验证过,不开long long,或者开的数据范围卡着200000,不是wa就是RE
所以啊,代码如下
1 #include <cstdio> 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 const int maxn = 200100; 6 long long n,weight[maxn]; 7 long long st[maxn],ed[maxn]; 8 vector <long long> num[maxn]; 9 long long start[maxn],end[maxn],pluss[maxn],tmp[maxn],tmp2[maxn]; 10 int main() 11 { 12 scanf ("%d",&n); 13 for (int i = 1;i <= n-1;i++) 14 { 15 scanf ("%d%d",&start[i],&end[i]); 16 num[start[i]].push_back(end[i]); 17 num[end[i]].push_back(start[i]); 18 } 19 for (int i = 1;i <= n;i++) 20 { 21 scanf ("%d",&weight[i]); 22 } 23 for (int i = 0;i < n;i++) 24 { 25 for (int j = 0;j < num[i].size();j++) 26 { 27 tmp[i]=max(tmp[i],weight[num[i][j]]); 28 } 29 } 30 for (int i = 0;i < n;i++) 31 { 32 for (int j = 0;j < num[i].size();j++) 33 { 34 if (weight[num[i][j]]==tmp[i]) 35 { 36 ed[i]=j; 37 break; 38 } 39 } 40 } 41 for (int i = 0;i < n;i++) 42 { 43 for (int j = 0;j < num[i].size();j++) 44 { 45 if (j!=ed[i]) 46 tmp2[i]=max(tmp2[i],weight[num[i][j]]); 47 } 48 } 49 long long answer=0; 50 for (int i = 0;i < n;i++) 51 { 52 answer=max(tmp[i]*tmp2[i],answer); 53 } 54 cout<<answer<<" "; 55 long long ans=0; 56 for (int i = 1;i < n;i++) 57 { 58 for (int j = 0;j < num[i].size();j++) 59 { 60 pluss[i]+=(weight[num[i][j]])%10007; 61 } 62 } 63 for (int i = 1;i < n;i++) 64 { 65 for (int j = 0;j < num[i].size();j++) 66 { 67 ans+=(pluss[i]-weight[num[i][j]])*weight[num[i][j]]%10007; 68 } 69 } 70 cout<<ans%10007; 71 return 0; 72 }
原文地址:https://www.cnblogs.com/very-beginning/p/11829461.html