[FZYZOJ 2044] [NOIP 2014 D1T2] 联合权值

[NOIP2014_D1_T2]联合权值

时间限制:1000MS

内存限制:131072KB

Description

无向连通图 G 有 n 个点,n−1 条边。点从 1 到 n 依次编号,编号为 i 的点的权值为 Wi,每条边的长度均为 1。图上两点 (u,v) 的距离定义为 u 点到 v 点的最短距离。对于图 G 上的点对 (u,v),若它们的距离为 2,则它们之间会产生Wv×Wu 的联合权值。

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

Input Format

第一行包含 1 个整数 n。

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

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

Output Format

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

Sample Input

5
1 2
2 3
3 4
4 5
1 5 2 3 10

Sample Output

20 74

Hint

距离为 2 的有序点对有(1,3),(2,4),(3,1),(3,5),(4,2),(5,3)。其联合权值分别为 2,15,2,20,15,20。其中最大的是 20,总和为 74。

对于30%的数据,1<n≤100;

对于60%的数据,1<n≤2000;

对于100%的数据,1<n≤200000,0<Wi≤10000。

保证一定存在可产生联合权值的有序点对。

【题解】

用边链表存储,枚举每个点,找到这个点连接的边,从他出发的两条边的终点间的距离即为2。

感谢 miskoo,只需要记录所有的和,然后加w*(t-w)即可。

↑这是一个高大上的方法↑

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,cnt=0;
 4 struct edge {
 5     int to,next;
 6 }e[400010];
 7 int w[200010];
 8 int head[200010];
 9 int ans=0,maxx=-1;
10 inline int read() {
11     int x=0,f=1;char ch;
12     ch=getchar();
13     while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch=getchar();}
14     while(ch<='9'&&ch>='0') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 void addedge(int u,int v) {
18     e[++cnt].to=v;
19     e[cnt].next=head[u];
20     head[u]=cnt;
21 }
22 int main() {
23     n=read();
24     for(int i=1;i<n;++i) {
25         int from,to;
26         from=read();to=read();
27         addedge(from,to);
28         addedge(to,from);
29     }
30     for (int i=1;i<=n;++i) w[i]=read();
31     for (int i=1;i<n;++i) {
32         int max1=-1,max2=-1,t=0,wx;
33         for (int j=head[i];j;j=e[j].next) {
34             wx=w[e[j].to];
35             t=t+wx,t%=10007;
36             if(wx>max1) {
37                 max2=max1;
38                 max1=wx;
39             }
40             else if(wx>max2) {
41                 max2=wx;
42             }
43         }
44         max1*=max2;
45         if(max1>maxx) maxx=max1;
46         for (int j=head[i];j;j=e[j].next) {
47             wx=w[e[j].to];
48             ans+=wx*(t-wx),ans%=10007; 
49         }
50     }
51     ans=(ans+10007)%10007;
52     printf("%d %d\n",maxx,ans);
53     return 0;
54 }
View Code

 

posted @ 2015-06-13 09:15  TonyFang  阅读(768)  评论(0编辑  收藏  举报