您的位置:首页 > 其它

Vijos1096 联合权值

2015-10-31 08:14 387 查看
前言:第一次参加NOIP时遇到的题。当时傻傻地用Floyd跑结果TLE,幸亏矩阵还没开爆。回想起来也是相当惊心动魄的……

思路:如果要一个个的找儿子再找孙子(因为这是一棵树,所以是可行的),O(n2),TLE。所以可以换一种思路,可以枚举中间点,这样也能得到同样的效果。但是单纯的枚举一个点后再找所有儿子,仍然是O(n2),仍TLE。其实仔细观察就可以发现,记sum[i]代表点i周围所有点的权值加和,那么对于i周围的某一点j,其总权值实际上就是w[j]*(sum[i]-w[j]),预处理一下,总复杂度就会降至O(n)。至于最大的权值,预处理时加以记录就行了。实际操作时不必建树,枚举边即可。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200005;
struct node
{
int u,v;
node(int u=0,int v=0):u(u),v(v){}
};
int n,w[maxn];
int sum[maxn];
int max1[maxn],max2[maxn];
node g[maxn];

void init()
{
memset(max1,0,sizeof(max1));
memset(max2,0,sizeof(max2));
scanf("%d",&n);
for (int i=1;i<n;++i)
{
int u,v;
scanf("%d%d",&u,&v);
g[i]=node(u,v);
}
for (int i=1;i<=n;++i)
scanf("%d",&w[i]);
}

void work()
{
int maxi=0;
for (int i=1;i<n;++i)
{
int a=g[i].u;
int b=g[i].v;
sum[a]+=w[b];
sum[b]+=w[a];
if (w[a]>max1[b])
{
max2[b]=max1[b];
max1[b]=w[a];
}
else
max2[b]=max(max2[b],w[a]);
if (w[b]>max1[a])
{
max2[a]=max1[a];
max1[a]=w[b];
}
else
max2[a]=max(max2[a],w[b]);
}
for (int i=1;i<n;++i)
maxi=max(maxi,max1[i]*max2[i]);
printf("%d ",maxi);
int ans=0;
int mod=10007;
for (int i=1;i<n;++i)
{
int a=g[i].u;
int b=g[i].v;
ans+=((sum[a]-w[b])%mod)*(w[b]%mod)%mod;
ans+=((sum[b]-w[a])%mod)*(w[a]%mod)%mod;
}
printf("%d",ans%mod);
}

int main()
{
init();
work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: