2014年 联合权值

联合权值
 
题目描述
无向连通图G 有n 个点,n - 1 条边。点从1 到n 依次编号,编号为 i 的点的权值为W i   ,每条边的长度均为1 。图上两点( u ,  v ) 的距离定义为u 点到v 点的最短距离。对于图G 上的点对( u, v) ,若它们的距离为2 ,则它们之间会产生Wu
×Wv 的联合权值。 
请问图G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少?
 
输入格式:
输入文件名为link .in。 
第一行包含1 个整数n 。 
接下来n - 1 行,每行包含 2 个用空格隔开的正整数u 、v ,表示编号为 u 和编号为v 的点之间有边相连。 
最后1 行,包含 n 个正整数,每两个正整数之间用一个空格隔开,其中第 i 个整数表示图G 上编号为i 的点的权值为W i 。
输出格式:
输出文件名为link .out 。 
输出共1 行,包含2 个整数,之间用一个空格隔开,依次为图G 上联合权值的最大值
和所有联合权值之和。由于所有联合权值之和可能很大,输出它时要对10007 取余。
 
输入样例: 

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

 

输出样例:
20 74
 
 说明
 

【数据说明】 
对于30% 的数据,1 < n≤ 100 ; 
对于60% 的数据,1 < n≤ 2000; 
对于100%的数据,1 < n≤ 200 , 000 ,0 < wi≤ 10, 000 。
 
//都知道(a+b)^2=a^2+2*a*b+b^2; 
//那么2*a1a2+2*a1*a3+2*a1*a4...+2*a(n-1)*an=(a1+a2+a3+...+an)^2-a1^2-a2^2-a3^2-...-an^2;
#include<cstdio>
#include<vector>
using namespace std;
int n,x,y,sz[200002],i;
bool f[200002];
int ansx=0,ans;
vector<int> map[200002];
int main(){
    scanf("%d",&n);
    for(i=1;i<=n;i++) map[i].push_back(0);
    for(i=1;i<n;i++){
        scanf("%d%d",&x,&y);
        map[x][0]++;
        map[x].push_back(y);
        map[y][0]++;
        map[y].push_back(x);//保存各点所连接的点; 
    }
    for(i=1;i<=n;i++) scanf("%d",&sz[i]);
    for(i=1;i<=n;i++){
        if(map[i][0]>1){
            int max1=0,max2=0;
            int fh=0,hf=0,g=0;
            int j;
            for(j=1;j<=map[i][0];j++){//找到最大的值; 
                if(sz[map[i][j]]>max1){
                    f[g]=0;
                    g=j;
                    max1=sz[map[i][j]];
                    f[j]=1;
                }
                hf=(hf+sz[map[i][j]])%10007;              //与第i个点相连的点的权值累和; 
                fh=(fh+sz[map[i][j]]*sz[map[i][j]])%10007;//与第i个点相连的点的权值的平方和 
            }
            for(j=1;j<=map[i][0];j++) if(sz[map[i][j]]>max2&&!f[j]) max2=sz[map[i][j]];//找第二大的值;
            f[g]=0;
            if(max1*max2>ansx) ansx=max1*max2;           //储存最大值; 
            while(hf<fh) hf+=10007;                      //取模后和的平方可能小于平方和,故+10007; 
            hf*=hf;
            hf=(hf-fh)%10007;
            ans=(ans+hf)%10007;                        
        }
    }
    printf("%d %d\n",ansx,ans);
    return 0;
}
View Code

 

posted @ 2016-04-02 20:12  qg1  阅读(140)  评论(0编辑  收藏  举报