您的位置:首页 > 其它

【NOIP2014】 联合权值

2016-07-29 21:30 281 查看
无向连通图 G 有 n 个点,n-1 条边。点从 1 到 n 依次编号,编号为 i 的点的权值为 
WiWi

每条边的长度均为 1。图上两点(u, v)的距离定义为 u 点到 v 点的最短距离。对于图 G 上的点对(u, v),若它们的距离为 2,则它们之间会产生
WuWu
×
WvWv
的联合权值。

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


输入格式

第一行包含 1 个整数 n。
接下来 n-1 行,每行包含 2 个用空格隔开的正整数 u、v,表示编号为 u 和编号为 v 的点 之间有边相连。
最后 1 行,包含 n 个正整数,每两个正整数之间用一个空格隔开,其中第 i 个整数表示 图 G 上编号为 i 的点的权值为
WiWi



输出格式

输出共 1 行,包含 2 个整数,之间用一个空格隔开,依次为图 G 上联合权值的最大值 和所有联合权值之和。由于所有联合权值之和可能很大,输出它时要对10007取余。

对于 30%的数据,1 < n ≤ 100;

对于 60%的数据,1 < n ≤ 2000;

对于 100%的数据,1 < n ≤ 200,000,0 < 
WiWi
 ≤
10,000

思路:乱搞

先想到暴力,然而暴力不好写那,于是想到每个点的出边与其距离为1,所以每个点的距离为1的结果是一定的,也就是说可以像DP一样利用起来,虽然是乘法,但是伟大的乘法分配驴就出现了!

然后统计最大值,一样的道理,不过由于对于一个定点,它去访问另外一个点的时候,预处理的最大值可能是它自己,所以最大值和次大值都需要存储,如果与最大值相等,那么就取次大值没跑了,否则就最大值。

我取模的姿势很挫,所以中途结果可能胡爆炸int,用了longlong,这在赛场上就是红果果的30分啊!!!

总的复杂度:统计权值和与极值,需要约n,然后计算更新需要n

所以最后应该是2n的算法

用了邻接表,这样明显快,用了读入优化,不过在vijos上ha

给你讲个笑话,有人在vijos上,把其他注释掉,只用cin读入不处理,然后最后三个点tle了

代码请食用~

#include<iostream>
#include<cstdio>
#include<cstring>
#include<limits.h>
#include<algorithm>
#include<vector>
#include<queue>
typedef long long ll;
using namespace std;
const int maxn=200005;
const ll Mod=10007;
ll an;
ll h[maxn];
vector<int> g[maxn];
ll mx[3][maxn];
ll sm[maxn];
void git(ll &iii)
{
iii=0;
int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){iii=iii*10+ch-'0';ch=getchar();}
if(f==-1) iii=-iii;
}
ll k, t2,n;
ll t1;
ll ans;
int main()
{
git(n);
for(int i=1;i<n;i++)
{
git(t1);git(t2);
g[t1].push_back(t2);
g[t2].push_back(t1);
}
for(int i=1;i<=n;i++)
git(h[i]);
for(int i=1;i<=n;i++)
{
if(g[i].empty())
continue;
int lm=g[i].size();
int f1=0,f2=0;
ll res=0;
for(int j=0;j<lm;j++)
{
res+=h[g[i][j]];
if(h[g[i][j]]>f1)
{
f2=f1;
f1=h[g[i][j]];
}
else
if(h[g[i][j]]==f1)
{
f2=h[g[i][j]];
}
else
if(h[g[i][j]]>f2)
{
f2=h[g[i][j]];
}
}
mx[0][i]=f1;
mx[1][i]=f2;
sm[i]=res;
}
for(int i=1;i<=n;i++)
{
if(g[i].empty())
continue;
int lm=g[i].size();
for(int j=0;j<lm;j++)
{
int nw=g[i][j];
ans+=h[i]*(sm[nw]-h[i]);
ans%=Mod;
if(mx[0][nw]==h[i])
{
an=max(an,mx[1][nw]*h[i]);
}
else
an=max(an,mx[0][nw]*h[i]);
}
}
cout<<an<<" "<<ans<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: