求助!缩点出度判断为什么是根据原图?
查看原帖
求助!缩点出度判断为什么是根据原图?
234964
2408727188GHR楼主2023/7/4 20:24

我看到 @来日方长 (第一篇题解)中,判断缩点后的出度是靠

if(id[w]!=id[u]) {
	du[id[w]]++;//遍历每一个点并记录出度
}

但是,如果在强连通分量中有两个点指向分量外的一个点。 丑图 如果按题解的算法来,算出缩点后出度为2,但是实际上是1,这不就错了吗? 另外,我考虑了一种算法

void rebuild() {
        rebuilt.resize(idx + 1);
        for(int i = 1; i <= n; i++) {
            for(auto j : g[i]) {
                rebuilt[belong[i]].push_back(belong[j]);
            }
        }
        for(int i = 1; i <= idx; i++) {
            sort(rebuilt[i].begin(), rebuilt[i].end());
            rebuilt[i].erase(std::unique(rebuilt[i].begin(), rebuilt[i].end()), rebuilt[i].end());
        }
    }

belong是节点编号对应强连通分量编号的关系。先暴力加边,然后排序去重rebuilt是重建后图的名字,g是原图的名字。 但是错了,48分。 这是我wa的完整代码

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <bitset>

class Popular {

    std::vector<int> belong;
    std::vector<std::vector<int>> g;
    std::vector<std::vector<int>> rebuilt;
    int n = 0, m = 0, ans = 0, idx = 0;

    void tarjan() {
        std::vector<int> dfn(n + 1), low(n + 1), stk;
        std::vector<bool> in_stk(n + 1);
        int time = 0;

        std::function<void(int)> dfs = [&](int pos)->void {
            dfn[pos] = low[pos] = ++time;
            stk.push_back(pos);
            in_stk[pos]= 1;
            for(auto i : g[pos]) {
                if(dfn[i]== 0) {
                    dfs(i);
                    low[pos] = std::min(low[pos], low[i]);
                } else if(in_stk[i]) {
                    low[pos] = std::min(low[pos], low[i]);
                }
            }
            if(low[pos] == dfn[pos]) {
                ++idx;
                while(stk.back() != pos) {
                    int now = stk.back();
                    belong[now] = idx;
                    in_stk[now] = false;
                    stk.pop_back();
                }
                int now = stk.back();
                belong[now] = idx;
                in_stk[now] = false;
                stk.pop_back();
            }
        };
        for(int i = 1; i <= n; i++) {
            if(dfn[i] != 0) {
                continue;
            }
            dfs(i);
        }
    }

    void rebuild() {
        rebuilt.resize(idx + 1);
        for(int i = 1; i <= n; i++) {
            for(auto j : g[i]) {
                rebuilt[belong[i]].push_back(belong[j]);
            }
        }
        for(int i = 1; i <= idx; i++) {
            sort(rebuilt[i].begin(), rebuilt[i].end());
            rebuilt[i].erase(std::unique(rebuilt[i].begin(), rebuilt[i].end()), rebuilt[i].end());
        }
    }

public:
    Popular() {
        using std::cin;
        cin >> n >> m;
        g.resize(n + 1);
        belong.resize(n + 1);
        for(int i = 1; i <= m; i++) {
            int u, v;
            cin>> u >> v;
            g[u].push_back(v);
        }
        for(int i = 1; i <= idx; i++) {
            sort(g[i].begin(), g[i].end());
            g[i].erase(std::unique(g[i].begin(), g[i].end()), g[i].end());
        }
    }
    void run() {
        tarjan();
        rebuild();
        int cnt = 0, pos = 0;
        for(int i = 1; i <= idx; i++) {
            if(rebuilt[i].empty()) {
                cnt++; pos = i;
            }
        }
        if(cnt != 1) {
            std::cout << '0';
        } else {
            cnt = 0;
            for(int i = 1; i <= n; i++) {
                if(belong[i] == pos) {
                    cnt++;
                }
            }
            std::cerr << pos << " ok\n";
            std::cout << cnt;
        }
    }
};

int main() {
    Popular solution;
    solution.run();
}

这是我按照题解判出度的方法改后, 应该 只改了判断出度有关

#include <iostream>
#include <vector>
#include <functional>

class Popular {

    std::vector<int> belong;
    std::vector<std::vector<int>> g;
    int n = 0, m = 0, idx = 0;

    void tarjan() {
        std::vector<int> dfn(n + 1), low(n + 1), stk;
        std::vector<bool> in_stk(n + 1);
        int time = 0;

        std::function<void(int)> dfs = [&](int pos) -> void {
            dfn[pos] = low[pos] = ++time;
            stk.push_back(pos);
            in_stk[pos] = true;
            for(auto i: g[pos]) {
                if(dfn[i] == 0) {
                    dfs(i);
                    low[pos] = std::min(low[pos], low[i]);
                } else if(in_stk[i]) {
                    low[pos] = std::min(low[pos], low[i]);
                }
            }
            if(low[pos] == dfn[pos]) {
                int now;
                ++idx;
                do {
                    now = stk.back();
                    belong[now] = idx;
                    in_stk[now] = false;
                    stk.pop_back();
                } while(now != pos);
            }
        };
        for(int i = 1; i <= n; i++) {
            if(dfn[i] != 0) {
                continue;
            }
            dfs(i);
        }
    }

public:
    Popular() {
        using std::cin;
        cin >> n >> m;
        g.resize(n + 1);
        belong.resize(n + 1);
        for(int i = 1; i <= m; i++) {
            int u, v;
            cin >> u >> v;
            g[u].push_back(v);
        }
        for(int i = 1; i <= idx; i++) {
            sort(g[i].begin(), g[i].end());
            g[i].erase(std::unique(g[i].begin(), g[i].end()), g[i].end());
        }
    }

    void run() {
        tarjan();
        int cnt = 0, pos = 0;
        std::vector<int> out(idx + 1);
        for(int i = 1; i <= n; i++) {
            for(int j : g[i]) {
                if(belong[i] != belong[j]) {
                    out[belong[i]]++;
                }
            }
        }
        for(int i = 1; i <= idx; i++) {
            if(out[i] == 0) {
                cnt++;
                pos = i;
            }
        }
        if(cnt != 1) {
            std::cout << '0';
        } else {
            cnt = 0;
            for(int i = 1; i <= n; i++) {
                if(belong[i] == pos) {
                    cnt++;
                }
            }
            std::cout << cnt;
        }
    }
};

int main() {
    Popular solution;
    solution.run();
}

最后,这道题判断出度只是有和无的关系,理论上来说,就算这里除了问题,应该也不会导致答案错误。 所以,这个问题有没有大佬帮忙解答一下啊

2023/7/4 20:24
加载中...