noip2014联合权值

来源:互联网 发布:扭矩补偿算法 编辑:程序博客网 时间:2024/05/21 09:55

这道题其实重点在于抓住一个细节,每条边的长度均为1,若它们的距离为2。

这代表着啥?

就是说,两两结点的联合权值,必定经过另外一个结点。所以说,枚举的时候,只需要枚举每一个结点以及与这个节点相邻的点。然后把这些结点两两配对相乘相加,就Ok了。可是,这样还是抄了。。。。怎么再优化?

我们再次分析一下。对于最大值,明显只需要贪心。在每个结点中选择最大的两个即可。这个不需要考虑。那么,总和值是否可以优化呢?假设一个结点o,与其相连结点的权值为a1,a2,a3,a4……ai,那么,答案sum=(a1*a2+a1*a3+……a1*ai)+(a2*a1+a2*a3+……a2*ai)+……+(ai*a1+ai*a2+……ai*ai-1)这个时候,再进行乘法结合律,我们发现,其实就是这些结点中,该结点的权值乘上所有结点权值减去他自己的权值。比较绕口,写成表达式就是aj*(sum[o]-aj)其中sum[o]表示的是与o相连的所有结点的权值之和。这样,预处理一下就Ok啦。算法的时间复杂度应该是O(kn),k应该是一个远远小于n的数吧

贴代码:

#include<cstdlib>

#include<iostream>

#include<cstring>

#include<algorithm>

#include<cstdio>

#include<cmath>

#include<vector>

#define mod 10007

using namespace std;

vector<int>a[200001];

int w[200001];

int sum[200001];

int main()

{

         intn;

         cin>>n;

         for(inti=1;i<=n-1;i++)

         {

                   intx,y;

                  scanf("%d%d",&x,&y);

                   a[x].push_back(y);

                   a[y].push_back(x);

         }

         for(inti=1;i<=n;i++) cin>>w[i];

         for(inti=1;i<=n;i++)

         {

                   for(intj=0;j<a[i].size();j++)

                   {

                            sum[i]+=w[a[i][j]];

                            sum[i]%=mod;

                   }

         }

         intans=0,maxn=0;

         for(inti=1;i<=n;i++)

         if(a[i].size()!=1)

         {

                   intmax1=w[a[i][0]];

                   intmax2=w[a[i][1]];

                   ans+=max1*(sum[i]-max1)+max2*(sum[i]-max2);

                   ans%=mod;

                   for(intj=2;j<a[i].size();j++)

                   {

                            intkk=w[a[i][j]];

                            inttt=kk;

                            if(tt>max1){swap(tt,max1);swap(tt,max2);}

                            elseif(tt>max2) {swap(tt,max2);}

                            ans+=kk*(sum[i]-kk);

                            ans%=mod;

                   }

                   maxn=max(maxn,max1*max2);

         }

         printf("%d%d\n",maxn,ans);

         return0;

}

0 0
原创粉丝点击