【NOIP2014】联合权值

本题在洛谷上的链接:https://www.luogu.org/problemnew/show/P1351


还是挺简单的,一看n个点,n-1条边,就知道是树,所以建一下树。联合权值要求两个点之间距离为2,而每条边的长度均为1,所以共有两种情况,其中一个点是另一个点的父亲的父亲;两个点父亲相同。

所以我们可以求出每个结点儿子的权值之和,及其权值最大值和次大值,之所以要求次大值,就是为了处理最大值就是本身的情况。

一开始用的DFS,爆栈了,只有50分,换成BFS,才有70分,而且提示的错误很乱,后来发现edge数组开小了,改完居然就A掉了。。。

#include <cstdio>
#include <algorithm>
#include <queue>

using namespace std;

inline int get_num() {
    int num = 0;
    char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9')
        num = num * 10 + c - '0', c = getchar();
    return num;
}

const int maxn = 2e5 + 5;

int head[maxn], eid;

struct Edge {
    int v, next;
} edge[2 * maxn];

inline void insert(int u, int v) {
    edge[++eid].v = v;
    edge[eid].next = head[u];
    head[u] = eid;
}

int w[maxn], sum[maxn], maxw[maxn][2], fa[maxn], as, am;

queue<int> q;

inline void bfs() {
    q.push(1);
    fa[1] = 1;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int p = head[u]; p; p = edge[p].next) {
            int v = edge[p].v;
            if (sum[v]) continue;
            fa[v] = u;
            q.push(v);
            sum[u] = (sum[u] + w[v]) % 10007;
            if (w[v] > maxw[u][0])
                maxw[u][1] = maxw[u][0], maxw[u][0] = w[v];
            else if (w[v] > maxw[u][1]) maxw[u][1] = w[v];
        }
    }
}

inline void bfs2() {
    q.push(1);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int p = head[u]; p; p = edge[p].next) {
            int v = edge[p].v;
            if (fa[u] == v) {
                as = (as + w[u] * (sum[v] - w[u]) % 10007) % 10007;
                if (w[u] == maxw[v][0])
                    am = max(am, w[u] * maxw[v][1]);
                else am = max(am, w[u] * maxw[v][0]);
            } else {
                as = (as + (2 * (w[u] * sum[v] % 10007) % 10007)) % 10007;
                am = max(am, w[u] * maxw[v][0]);
                q.push(v);
            }
        }
    }
}

int main() {
    int n, u, v;
    n = get_num();
    for (int i = 1; i < n; ++i) {
        u = get_num(), v = get_num();
        insert(u, v);
        insert(v, u);
    }
    for (int i = 1; i <= n; ++i)
        w[i] = get_num();
    bfs();
    bfs2();
    printf("%d %d", am, as);
    return 0;
}
AC代码
原文地址:https://www.cnblogs.com/Mr94Kevin/p/9836663.html