zoukankan      html  css  js  c++  java
  • 联合权值 vijos 1906 NOIP2014 D1T2 图结构

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

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

    本题O(N2)枚举可以拿60分,注意到有序点对中(a,b)和(b,a)是一样的,并以此优化(只算 a<b 的情况,最终的和乘以2,最大值不受影响),可以拿70分。

    正解需要推一下公式。

    因为本题是n个点、n-1条边,所以一定是一棵树。对于一个点N及其所连的两个不同点A、B,可以知道DAB=DAN+DNB=2;即对于一个点,设其相邻的点构成集合E,那么集合E中的任意点两两组合出来的点对(A,B),一定有AB最短路是2,符合题目要求,可以计算联合权值。

    我们设A、B、C三个点与D相连,权值分别为a、b、c,那么他们贡献的联合权值为  (ab+bc+ac)*2

    眼熟么?想一想(a+b+c)2=a2+b2+c2+2ab+2bc+2ac,那么上式等价:(a+b+c)2-(a2+b2+c2

    那么我们枚举每一个点,拿到其所相邻的点的平方和,即可求出这个点的所有相邻点贡献的全部联合权值(和的平方减去平方和)。

    注意,中间过程的数比较大,可能需要开long long来运算。

    这个是和的解法。那么最大值呢?

    我们在计算的时候,取点N的相邻点中最大的权值w1、w2,那么点N的相邻点能形成的最大联合权值一定是w1*w2,我们以此更新答案即可。

    附上AC代码

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<queue>
     6 #include<iostream>
     7 using namespace std;
     8 template<class T> inline void read(T &_a){
     9     bool f=0;int _ch=getchar();_a=0;
    10     while(_ch<'0' || _ch>'9'){if(_ch=='-')f=1;_ch=getchar();}
    11     while(_ch>='0' && _ch<='9'){_a=(_a<<1)+(_a<<3)+_ch-'0';_ch=getchar();}
    12     if(f)_a=-_a;
    13 }
    14 
    15 const int maxn=1200001,modx=10007;
    16 struct edge
    17 {
    18     int to,next;
    19 }e[maxn<<1];
    20 long long n,egcnt,head[maxn],w[maxn],maxx,sum;
    21 
    22 inline void addedge(int from,int to)
    23 {
    24     e[++egcnt].to=to;
    25     e[egcnt].next=head[from];
    26     head[from]=egcnt;
    27     e[++egcnt].to=from;
    28     e[egcnt].next=head[to];
    29     head[to]=egcnt;
    30 }
    31 
    32 int main()
    33 {
    34     read(n);
    35     for (register int i=1,a,b;i<n;++i) read(a),read(b),addedge(a,b);
    36     for (register int i=1;i<=n;++i) read(w[i]);
    37     for (register int i=1;i<=n;++i)
    38     {
    39         long long cnt1=0,cnt2=0,maxx1=0,maxx2=0;
    40         for (register int v=head[i];v;v=e[v].next)
    41         {
    42             cnt1+=w[e[v].to];
    43             cnt2+=w[e[v].to]*w[e[v].to];
    44             cnt1%=modx;
    45             cnt2%=modx;
    46             if(w[e[v].to]>maxx1) maxx2=maxx1,maxx1=w[e[v].to];
    47              else if (w[e[v].to]>maxx2) maxx2=w[e[v].to];
    48         }
    49         sum+=(cnt1*cnt1%modx-cnt2+modx)%modx;
    50         sum%=modx;
    51         maxx=max(maxx,maxx1*maxx2);
    52     }
    53     printf("%lld %lld",maxx,sum%modx);
    54     return 0;
    55 }
    View Code
  • 相关阅读:
    Linux系统管理10-----进程和计划任务管理
    07作业进程和任务管理
    Linux系统管理09-----引导过程与服务过程
    网站部署流程
    Docker 安装与使用
    基于NFS共享实现kvm虚拟主机
    GlusterFS 部署
    rsync 远程同步服务部署
    Zabbix 通过 JMX 监控 tomcat
    Zabbix 简单错误 解决方法
  • 原文地址:https://www.cnblogs.com/jaywang/p/7742145.html
Copyright © 2011-2022 走看看