为什么手写栈会错#29#30?

P8436 【模板】边双连通分量

sxhy @ 2024-03-30 17:23:28

stl的栈100分

#include<bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int n, m, dfn[N], low[N],cnt, tot, top, cut[N];
int root;

struct edge {
    int u, v;
};
vector<edge>e;
vector<int>h[2 * N], edcc[N];
stack<int>stk;
void add(int a, int b) {
    e.push_back({ a,b });
    h[a].push_back(e.size() - 1);
}
void tarjan(int x, int inedge) {
    dfn[x] = low[x] = ++tot;
    stk.push(x);
    for (int i = 0; i < h[x].size(); i++) {
        int bian = h[x][i], v = e[bian].v;
        if (!dfn[v]) {
            tarjan(v, bian);
            low[x] = min(low[x], low[v]);
            if (low[v] > dfn[x]) {
                cut[bian] = cut[(bian ^ 1)] = 1;
            }
        }
        else if (bian != (inedge ^ 1)) {
            low[x] = min(low[x], dfn[v]);
        }
    }
    if (low[x] == dfn[x]) {
        int y;
        cnt++;
        while (1) {
            y = stk.top(), stk.pop();
            edcc[cnt].push_back(y);
            if (y == x)break;
        }

    }

}
int main() {
    int a, b;
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        cin >> a >> b;
        add(a, b), add(b, a);
    }
    for (int i = 1; i <= n; i++) {
        if (!dfn[i])tarjan(i, 0);
    }
    cout << cnt << "\n";
    for (int i = 1; i <= cnt; i++) {
        cout << edcc[i].size() << " ";
        for (int j = 0; j < edcc[i].size(); j++) {
            cout << edcc[i][j] << " ";
        }
        puts("");
    }

}

手写栈89分

#include<bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int n, m, dfn[N], low[N], stk[N], cnt, tot, top, cut[N];
int root;

struct edge {
    int u, v;
};
vector<edge>e;
vector<int>h[2 * N], edcc[N];
void add(int a, int b) {
    e.push_back({ a,b });
    h[a].push_back(e.size() - 1);
}
void tarjan(int x, int inedge) {
    dfn[x] = low[x] = ++tot;
    stk[++top] = x;
    for (int i = 0; i < h[x].size(); i++) {
        int bian = h[x][i], v = e[bian].v;
        if (!dfn[v]) {
            tarjan(v, bian);
            low[x] = min(low[x], low[v]);
            if (low[v] > dfn[x]) {
                cut[bian] = cut[(bian ^ 1)] = 1;
            }
        }
        else if (bian != (inedge ^ 1)) {
            low[x] = min(low[x], dfn[v]);
        }
    }
    if (low[x] == dfn[x]) {
        int y;
        cnt++;
        while (1) {
            y = stk[top];
            top--;
            edcc[cnt].push_back(y);
            if (y == x)break;
        }

    }

}
int main() {
    int a, b;
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        cin >> a >> b;
        add(a, b), add(b, a);
    }
    for (int i = 1; i <= n; i++) {
        if (!dfn[i])tarjan(i, 0);
    }
    cout << cnt << "\n";
    for (int i = 1; i <= cnt; i++) {
        cout << edcc[i].size() << " ";
        for (int j = 0; j < edcc[i].size(); j++) {
            cout << edcc[i][j] << " ";
        }
        puts("");
    }

}

by DAMDAM @ 2024-03-30 18:34:13

N 开大点就过了。。。 @sxhy


by DAMDAM @ 2024-03-30 18:35:53

因为边表要开两倍,cut 数组跟着也要开两倍


by Rosick @ 2024-03-30 18:37:23

cut数组没用,且超限了,如果手写栈,就会修改到里面的内容,而stl的不会 @sxhy


by sxhy @ 2024-03-30 18:40:20

@DAMDAM 感谢!我超,什么原理


by Atri_Lobato @ 2024-08-27 10:04:26

@sxhy 正反边建两次qaq我也错了


|