圖論強連通專題:POJ2762

題目描述:

給出圖中一些點的連通關係,判斷任意圖中兩個點是否能從u到v或者v到u。

大致思路:

思路還是先用強連通縮點,之後對於這個圖進行拓撲排序,如果在排序過程中出現並列搜索的點了,也就是說這個子圖中有多個起點,也就是說一定存在(u,v)不能u到v或者v到u。

代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

const int maxn = 1000 + 10;
bool g[maxn][maxn];
vector<int> gg[maxn];
vector<int> G[maxn];
vector<int> rG[maxn];
vector<int> vs;
bool used[maxn];
int n,m;
int cmp[maxn];
bool vis[maxn];
int v_in[maxn];
queue<int> s;

void add_edge(int from, int to) {
    G[from].push_back(to);
    rG[to].push_back(from);
}

void dfs(int v) {
    used[v] = true;
    for (int i = 0; i < G[v].size(); i++) {
        if (!used[G[v][i]]) dfs(G[v][i]);
    }
    vs.push_back(v);
}

void rdfs(int v, int k) {
    used[v] = true;
    cmp[v] = k;
    for (int i = 0; i < rG[v].size(); i++) {
        if (!used[rG[v][i]]) rdfs(rG[v][i],k);
    }
}

int scc() {
    memset(used,0,sizeof(used));
    vs.clear();
    for (int i = 1; i <= n; i++) {
        if (!used[i]) dfs(i);
    }
    memset(used,0,sizeof(used));
    int k = 0;
    for (int i = vs.size() - 1; i >=0; i--) {
        if (!used[vs[i]]) rdfs(vs[i],k++);
    }
    return k;
}

bool top_sort(int n) {
    if (n == 1) return true;
    bool f = true;
    for (int i = 0; i < n; i++)
        if (!v_in[i] && f) {
            s.push(i);
            f = false;
        }
        else if (!v_in[i]) return false;
    while (!s.empty()) {
        int u = s.front();s.pop();
        f = true;
        for (int i = 0; i < gg[u].size(); i++) {
            v_in[gg[u][i]]--;
            if (!v_in[gg[u][i]] && f) {
                s.push(gg[u][i]);
                f = false;
            }
            else if (!v_in[gg[u][i]]) return false;
        }
    }
    return true;
}

int main() {
    int t;
    cin>>t;
    while (t--) {
        cin>>n>>m;
        while (!s.empty()) s.pop();
        for (int i = 0; i <= n; i++) {
            G[i].clear();
            rG[i].clear();
            gg[i].clear();
        }
        for (int i = 0; i < m; i++) {
            int a,b;
            scanf("%d%d",&a,&b);
            add_edge(a,b);
        }
        int nN = scc();
        memset(g,0,sizeof(g));
        memset(v_in,0,sizeof(v_in));
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < G[i].size(); j++) {
                if (cmp[i] != cmp[G[i][j]] && !g[cmp[i]][cmp[G[i][j]]]) {
                    g[cmp[i]][cmp[G[i][j]]] = true;
                    v_in[cmp[G[i][j]]] ++;
                    gg[cmp[i]].push_back(cmp[G[i][j]]);
                }
            }
        }
        memset(vis,0,sizeof(vis));
        if (top_sort(nN)) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章