真搞不懂为什么全RE了,交了10+遍了,在洛谷IDE上都没RE
查看原帖
真搞不懂为什么全RE了,交了10+遍了,在洛谷IDE上都没RE
565040
Conan15楼主2023/5/1 20:35

管理员聚聚别封我,不是滥用评测器,只是想知道是因为什么RE,QaQ

初步判定是kruskal的“if (Fa != Fb) { p[Fa] = Fb;……}”部分有问题,求改

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = 6e5 + 10;
const int INF = 0x3f3f3f3f;

int p[N], n, m;

struct E {
    int a, b, w;
    bool operator< (const E &W) const {
        return w < W.w;
    }
} edge[M];

int find(int x) {
    if (p[x] != x) p[x] = find(p[x]);
    else return x;
}

int use[M]; //是否在最小生成树内
int res = 0;

int h[N], e[M], w[M], ne[M], idx;
void add(int a, int b, int c)  // 添加一条边a->b,边权为c
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}


void kruskal() {
    int cnt = 0;
    for (int i = 1; i <= m; i++) {
        int a = edge[i].a, b = edge[i].b, w = edge[i].w;
        int Fa = find(a), Fb = find(b);
        if (Fa != Fb) {
            p[Fa] = Fb;
            use[i] = true; //在最小生成树内
            add(a, b, w); add(b, a, w); //建树
            cnt++; res += w;
        }
        if (cnt == n - 1) return;
    }
}

int fa[N][30], fi[N][30], se[N][30];    //2^i级祖先,倍增路径最大次大值
int dep[N];

void dfs(int u, int father) {
    dep[u] = dep[father] + 1; fa[u][0] = father;
    for (int i = h[u]; ~i; i = ne[i]) {
        int v = e[i];
        if (v == father) continue;
        fi[v][0] = w[i];
        dfs(v, u);  
    }
}

int lca(int x, int y) {
    if (dep[x] < dep[y]) swap(x, y);
    for (int i = 15; i >= 0; i--)
        if (dep[fa[x][i]] >= dep[y]) x = fa[x][i];
    if (x == y) return x;
    for (int i = 15; i >= 0; i--)
        if (fa[x][i] != fa[y][i])  x = fa[x][i], y = fa[y][i];
    return fa[x][0];
}

void init() {
    for (int i = 1; i <= 15; i++) {
        for (int j = 1; j <= n; j++) {
            fa[j][i] = fa[fa[j][i - 1]][i - 1];
            fi[j][i] = max(fi[j][i - 1], fi[fa[j][i - 1]][i - 1]);
            se[j][i] = max(se[j][i - 1], se[fa[j][i - 1]][i - 1]);
            if (fi[j][i - 1] < fi[fa[j][i - 1]][i - 1]) se[j][i] = max(se[j][i], fi[j][i - 1]);
            else if (fi[j][i - 1] > fi[fa[j][i - 1]][i - 1]) se[j][i] = max(se[j][i], fi[fa[j][i - 1]][i - 1]);
        }
    }
}

int Max(int u, int grandpa, int q) {
    int ans = 0;
    for (int i = 15; i >= 0; i--) {
        if (dep[fa[u][i]] >= dep[grandpa]) {    //拆分成log个小段计算
            if (fi[u][i] == q) ans = max(ans, se[u][i]);
            else ans = max(ans, fi[u][i]);
            u = fa[u][i];
        }
    }
    return ans;
}

int ans = 0;

int main() {
    memset(h, -1, sizeof h);
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) p[i] = i;
    for (int i = 1; i <= m; i++) {
        int a, b, c; scanf("%d%d%d", &a, &b, &c);
        edge[i] = {a, b, c};
    }
    sort(edge + 1, edge + 1 + m);
    kruskal();
    dfs(1, 0);
    init();
    ans = INF;
    for (int i = 1; i <= m; i++) {
        if (use[i]) continue;   //选择非树边进行计算
        int u = edge[i].a, v = edge[i].b, z = edge[i].w;
        int LCA = lca(u, v);
        int m1 = Max(u, LCA, z), m2 = Max(v, LCA, z);
        //cout << i << ' ' << m1 << ' ' << m2 << endl;
        if (max(m1, m2) != z) ans = min(ans, res + z - max(m1, m2));
    }
    printf("%d\n", ans);
    //for (int i = 0; i <= 5; i++, puts(""))
    //    for (int j = 1; j <= n; j++) cout << se[j][i] << ' ';
    return 0;
}
2023/5/1 20:35
加载中...