20pts, #2#4AC, 其他全WA求助
查看原帖
20pts, #2#4AC, 其他全WA求助
403719
Kasugano_Haruka楼主2022/3/18 11:18

思路是并查集查询森林里每棵基环树多出来的那条边存起来. 对于每一条这样的边都做3次dfs, 对应了多余的这条边的两个端点同时不选或只选一个的三种情况, 取最大.(其实就是拿城市环路的代码改的

评论区给的hack数据都试过没有问题, 1恨2,2恨1的重边也试过了貌似没问题, 求改正或hack, 万分感谢!

代码如下:

#include <bits/stdc++.h>

#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define abs(x) ((x) >= 0 ? (x) : -(x))
#define endl '\n'

using namespace std;

__attribute__((unused)) typedef long long ll;
__attribute__((unused)) typedef unsigned long long ull;

__attribute__((unused)) inline ll read() {
    ll x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}

__attribute__((unused)) const long double Pi = 3.1415926535897932384626433832795;
__attribute__((unused)) const int maxN = 1e6 + 4, maxM = 1e5 + 4, maxA = 14, maxB = 34, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n;
int p[maxN] = {};
int father[maxN] = {}, Rank[maxN] = {};

void init() {
    for (int i = 1; i <= n; ++i) {
        father[i] = i;
        Rank[i] = 1;
    }
}

int find(int x) {
    return x == father[x] ? x : find(father[x]);
}

void merge(int i, int j) {
    int x = find(i), y = find(j);
    if (Rank[x] <= Rank[y]) {
        father[x] = y;
    } else
        father[y] = x;
    if (Rank[x] == Rank[y] && x != y) {
        ++Rank[y];
    }
}

/**
for (int i = head[u]; ~i; i = nxt[i]) {
    int v = to[i];
}
 */

vector<int> nxt, head, to;

void add(int u, int v) {
    nxt.push_back(head[u]);
    head[u] = to.size();
    to.push_back(v);
}

ll dp[2][maxN] = {};
bool checked[2][maxN] = {};

ll dfs(bool isChosen, int u, int fa, int ign) {
    if (checked[isChosen][u])
        return dp[isChosen][u];

    ll tmp = p[ign];
    if (fa == -1) {
        p[ign] = -INF;
    }
    checked[isChosen][u] = true;
    ll ans = isChosen ? p[u] : 0;
    for (int i = head[u]; ~i; i = nxt[i]) {
        int v = to[i];
        if (v == fa)
            continue;
        if (isChosen) {
            ans += dfs(false, v, u, ign);
        } else {
            ans += max(dfs(true, v, u, ign), dfs(false, v, u, ign));
        }
    }

    if (fa == -1) {
        p[ign] = tmp;
    }
    return dp[isChosen][u] = ans;
}

vector<int> x, y;

int main() {
    n = read();
    head.resize(n + 1, -1);
    init();
    int v;
    for (int i = 1; i <= n; ++i) {
        p[i] = read(), v = read();
        if (find(i) == find(v)) {
            x.push_back(i);
            y.push_back(v);
            continue;
        }
        merge(i, v);
        add(i, v);
        add(v, i);
    }
    if (n == 1) {
        cout << p[1];
        return 0;
    }

    ll ans = 0;
    for (int i = 0; i < x.size(); ++i) {
        ll tmp = max(dfs(true, x[i], -1, y[i]), dfs(false, x[i], -1, y[i]));
        memset(dp, 0, sizeof dp);
        memset(checked, 0, sizeof checked);
        tmp = max(tmp, dfs(true, y[i], -1, x[i]));
        ans += tmp;
    }

    cout << ans;

    return 0;
}
2022/3/18 11:18
加载中...