您的位置:首页 > 其它

#NOIP 2014# day.1 T2 联合权值

2016-07-26 09:03 459 查看
题目和数据在评论中给出地址。或者自行在网上搜索,这里就不再给出。

第一眼看起来很复杂。

所以我想了个对链、和树不同情况都分别处理的算法。。orz。。复杂度太高最后4组T了。。

所以。。转换思路。。

联合权值 w[i]*w[j]。i,j距离为2.也就是i,j中间间隔了一个节点,所以我们在遍历这个中间节点的时候处理。

题目求最大和总和,

先考虑最大,我们只需要对节点U维护一个_max1,_max2最大值和次大值。

然后_max1*_max2 和总的 maxw比。maxw取大。

然后就是两两和。

先考虑U点只有3个子节点 a,b,c

则 tot = (a * b + b * c + c * a)*2 % mod

而(a + b + c)^2 = a^2 + b^2 + c^2 + 2ab + 2ac +2bc ;

2ab + 2ac +2bc = (a + b + c)^2 - (a^2 + b^2 + c^2 ).

所以..

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#define maxn 600010
using namespace std;
struct Edge {
int v,next;
}e[maxn];
long long p[maxn],w[maxn], en = 0;
int f[maxn];
void add(int u, int v) {
en ++;
e[en].v = v;
e[en].next = f[u];
f[u] = en;
}
int main()
{
freopen("link.in","r",stdin);
freopen("link.out","w",stdout);
int n,u,v;
cin >> n;
for (int i = 1; i <= n; ++i) f[i] = -1;
for (int i = 1; i < n; ++i) {
scanf("%d %d", &u, &v);
add(u,v);
add(v,u);
}
long long total = 0, max = 0;
for (int i = 1; i <= n; ++i) scanf("%d", &w[i]);
for (int i = 1; i <= n; ++i) {
int cnt = 0;
long long sum1= 0;
int max1 = 0, max2 = 0;
for (int j = f[i]; j != -1; j = e[j].next) {
p[++cnt] = w[e[j].v];
sum1 = (sum1 + p[cnt]) % 10007;
total = (total - p[cnt] * p[cnt] + 10007) % 10007;
if (p[cnt] > max1) max2 = max1, max1 = p[cnt];
else
if (p[cnt] > max2)
max2 = p[cnt];
}
if (cnt > 0) {
total = (total + sum1 * sum1) % 10007;
}
if (total < 0) total += 10007;
if (max1 * max2 > max) max = max1 * max2;
}
cout <<max<<" "<<total<<endl;
return 0;
}


再给出一份搜索的代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
int n;
#define maxn 200001
#define mod 10007
vector<int> e[maxn];
int w[maxn];
int maxw = 0;
int tot  = 0;
bool vis[maxn];
void dfs(int u,int fa)
{

vis[u] = 1;
int len = e[u].size();
int _max1 = w[fa],_max2 = 0;
int sum = 0,dsum = 0,v;
for(int i=0;i<len;i++)
{

v = e[u][i];
if(!vis[v]&&v!=fa)
{

if(w[v]>_max1)
{
_max2 = _max1;
_max1 = w[v];
}
else if(w[v]>_max2)
{
_max2 = w[v];
}
dfs(v,u);
sum += w[v];
sum %= mod;
dsum += w[v]*w[v];
dsum %= mod;
}
}
tot += ((long long)sum*w[fa]*2)%mod;
tot += ((long long)sum*sum%mod - dsum + mod)%mod;
tot %= mod;
maxw = max(maxw,_max1*_max2);

}
int main()
{
#define LOC
#ifdef LOC
freopen("link.in","r",stdin);
freopen("link.out","w",stdout);
#endif
scanf("%d",&n);
int a,b;
int root = 0;
maxw = 0;
tot  = 0;
for(int i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
e[a].push_back(b);
e[b].push_back(a);
}
for(int i=1;i<=n;i++)scanf("%d",&w[i]);
w[0]=0;
dfs(1,0);
printf("%d %d",maxw,tot);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  NOIP