您的位置:首页 > 其它

【NOIP2014 联合权值】

2016-11-08 20:12 375 查看
#include <cstdio>
#include <climits>

const int MAXN = 200000 + 5;
int MOD = 10007;

struct Node;
struct Edge;

struct Node {
int w;
Edge *lastE;
}N[MAXN];

struct Edge {
Node *from, *to;
Edge *next;

Edge (Node *from, Node *to) : from(from), to(to), next(from->lastE) {}
};

void AddEdge(int u, int v)
{
N[u].lastE = new Edge(&N[u], &N[v]);
N[v].lastE = new Edge(&N[v], &N[u]);
}

int n;
long long ans;

int main()
{
scanf("%d", &n);
for (int i = 0; i < n - 1; i++)
{
int u, v;
scanf("%d %d", &u, &v);
AddEdge(u, v);
}

for (int i = 1; i <= n; i++) scanf("%d", &N[i].w);

int MAX = INT_MIN;

for (int i = 1; i <= n; i++)
{
long long m = 0; //定义在函数内的变量要记得赋初值
int MAXm = 0, MINm = 0;

for (Edge *e = N[i].lastE; e; e = e->next)
{
if (e->to->w >= MAXm){
MINm = MAXm;
MAXm = e->to->w;
}
else if (e->to->w >= MINm)
MINm = e->to->w;  //这点没想到,这个点有可能是虽然不是最大的,但是是次大的
m += e->to->w; //这里m有可能爆int,所以要用long long
}

for (Edge *e = N[i].lastE; e; e = e->next)
{
(ans += ((m - e->to->w) * e->to->w) % MOD) %= MOD;
}

if (MAXm * MINm > MAX)
{
MAX = MAXm * MINm;
}
}

printf("%d %lld\n", MAX, ans);
return 0;
}


代码是Sulfur6_L8972帮忙debug过的。

方法是Rachel教的。

就是一个点,以它为中心,周围所有点的联合权值之和为每一个互相相乘。例如有四个点A、B、C、D,和就为     A*B+A*C+A*D+B*A+B*C+B*D+C*A+C*B+C*D+D*A+D*B+D*C

= A(B+C+D)+B(A+C+D)+C(A+B+D)+D(A+C+D)

=A(m-A)+B(m-B)+C(m-C)+D(m-D).

但是教了方法我也懂了之后还是没能调出来,就是我的细节的锅了。不过感觉最近做了些题,积累了一些常见的错误及调试方法,也算有些收获。

主要的bug都在程序里注释出来了,另外还要注意主函数里的变量在哪里需要被重新定义,它的范围到哪里。

Sulfur6_L8972说也可以把
m += e->to->w;
改成
m = (m + e->to->w) % MOD;
但是模出来有可能是负的,需要在最后在加上啥啥啥再模一遍。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: