zoukankan      html  css  js  c++  java
  • code3728 联合权值

    一开始暴搜,超时3个点...

    后来看了题解:

    首先,两个点的距离为2当且仅当它们都与一个点直接相连

    反过来说,一个点所有的出边的终点都是互相距离2的(最大值可以依靠这个方法,前向星处理的时候将每个点的最大出点和次大出点存起来,最后过一遍比较乘积)

    那么,所有点对的权值和就是每一个点所产生的点对权值和的总和

    但此时,如若要对每一个点的出点进行两两配对,每一个点需要O(e^2)(e为该点出度)

    只要有一个点有太多的出边就会TLE,此时我们我可以利用乘法分配律

    w[i]*w[j1]+w[i]*w[j2]+...+w[i]*w[jn]=w[i]*(w[j1]+...+w[jn])

    我们定义一个点的围权和为到该点距离为1的点的权值和

    从这个式子中,我们可以看见:i点所产生的权值和,相当于是与i点直接相连的那些点中(j1,j2,j3...),每个点(j1,j2,j3)的围权和的和,每个围权和减去自己本身,再乘以该点权值

    再利用前向星存储,这样时间复杂度会直接降到O(n)

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define Size 200005
    using namespace std;
    
    int IN[Size][2];
    
    struct node{
        int to;
        int next;
    }edge[Size*2];
    int head[Size];
    
    int n;
    int w[Size];
    long long sum=0; int largest=-1;
    int L[Size][2];
    long long d[Size];
    
    void check(int a,int b){
        int ww=w[b];
        if(ww>L[a][0]){
            L[a][1]=L[a][0];
            L[a][0]=ww;
        }else if(ww>L[a][1])L[a][1]=ww;
    }
    
    int main(){
        memset(head,-1,sizeof(head));
        freopen("3728.in","r",stdin);
        
        cin>>n;
        int a,b;
        for(int i=1;i<n;i++)scanf("%d%d",&IN[i][0],&IN[i][1]);
        for(int i=1;i<=n;i++)scanf("%d",w+i);
        for(int i=1;i<n;i++){
            a=IN[i][0]; b=IN[i][1];
            edge[i*2-1].to=b; edge[i*2-1].next=head[a]; head[a]=2*i-1;
            check(a,b); d[a]+=w[b];
            edge[i*2].to=a; edge[i*2].next=head[b]; head[b]=2*i;
            check(b,a); d[b]+=w[a];
        }
        
        for(int i=1;i<=n;i++){
            largest=max(largest,L[i][0]*L[i][1]);
        }
        for(int i=1;i<=n;i++){
            for(int j=head[i];j!=-1;j=edge[j].next){
                int x=edge[j].to;
                sum+=(w[x]*(d[i]-w[x])%10007)%10007;
                sum%=10007;
            }
        }
        
        cout<<largest<<' '<<sum<<endl;
        
        return 0;
    }
  • 相关阅读:
    ORBSLAM2的资源
    工程思想
    Linux中PATH、 LIBRARY_PATH、 LD_LIBRARY_PATH和ROS_PACKAGE_PATH
    CMkeList文件编写
    SLAM资料
    windows下隐藏文件夹
    Ubuntu16装Flash
    知识管理
    学习纲领
    lsof详解
  • 原文地址:https://www.cnblogs.com/FuTaimeng/p/5606514.html
Copyright © 2011-2022 走看看