码迷,mamicode.com
首页 > 其他好文 > 详细

树的问题--P1351 联合权值

时间:2019-11-10 13:29:55      阅读:78      评论:0      收藏:0      [点我收藏+]

标签:minus   格式   正整数   问题   mes   相加   std   编号   cto   

题目描述

无向连通图 GGG 有 nnn 个点,n−1n-1n1 条边。点从 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-1n1 行,每行包含 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 }

 

树的问题--P1351 联合权值

标签:minus   格式   正整数   问题   mes   相加   std   编号   cto   

原文地址:https://www.cnblogs.com/very-beginning/p/11829461.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!