poj 2762 Going from u to v or from v to u(targan縮點+拓撲排序)

題目鏈接:http://poj.org/problem?id=2762

給定頂點和邊的關係,問是否對於任意的頂點x和y,總存在x到y的路徑或y到x的路徑,一開始看成和的關係,判斷只有一個連通分量。

如果是或的話,就是對於縮點後的圖看看能不能找到一條路徑貫穿所有的點,用拓撲排序更新出到達每個頂點最多能有幾個頂點。然後如果頂點個數=強連通分量數,那麼就是符合題意的。


附上測試數據和代碼:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;

const int maxn = 1002;
const int maxm = 6005;
int n, m;

int head[maxn];
struct E {
    int to;
    int next;
} edge[maxm];

int dfn[maxn];
int low[maxn];
bool instack[maxn];
int stap[maxn];
int belong[maxn];
vector<int> G[maxn];
int indeg[maxn];
int index, cur, cnt, eid;
int dis[maxn];

void addedge(int from, int to) {
    edge[eid].to = to;
    edge[eid].next = head[from];
    head[from] = eid ++;
}

void targan(int v) {
    dfn[v] = low[v] = ++index;
    instack[v] = true;
    stap[++cur] = v;
    for (int i = head[v]; ~i; i = edge[i].next) {
        int to = edge[i].to;
        if(!dfn[to]) {
            targan(to);
            low[v] = min(low[v], low[to]);
        } else if(instack[to]) {
            low[v] = min(low[v], dfn[to]);
        }
    }
    if(dfn[v] == low[v]) {
        cnt ++;
        int j;
        do {
            j = stap[cur--];
            instack[j] = false;
            belong[j] = cnt;
        } while (j != v);
    }
}
void suo() {
    for(int i = 1; i <= cnt; i ++) {
        G[i].clear();
        indeg[i] = 0;
    }
    for (int i = 1; i <= n; i ++) {
        for (int j = head[i]; ~j; j = edge[j].next) {
            if(belong[i] != belong[edge[j].to]) {
                G[belong[i]].push_back(belong[edge[j].to]);
                indeg[belong[edge[j].to]] ++;
            }
        }
    }
}
bool topo() {
    queue<int> que;
    for (int i = 1; i <= cnt; i ++) {
        if(indeg[i] == 0) {
            que.push(i);
            dis[i] = 1;
        }
        else {
            dis[i] = 0;
        }
    }
    while(!que.empty()) {
        int cur = que.front();
        que.pop();
        for(int i = 0; i < G[cur].size(); i ++) {
            int to = G[cur][i];
            dis[to] = max(dis[to], dis[cur] + 1);
            indeg[to] --;
            if(indeg[to] == 0) {
                que.push(to);
            }
        }
    }
    for(int i = 1; i <= cnt; i ++) {
        if(dis[i] == cnt) {
            return true;
        }
    }
    return false;
}
int main() {
    int x, y, t;
//    freopen("1.in", "r", stdin);
    scanf("%d", &t);
    while (t --) {
        scanf("%d%d",&n, &m);
        memset(head, -1, sizeof(head));
        memset(dfn, 0, sizeof(dfn));
        memset(instack, false, sizeof(instack));
        eid = 0;
        for (int i = 0; i < m; i ++) {
            scanf ("%d%d", &x, &y);
            addedge(x, y);
        }
        cur = index = cnt = 0;
        for (int i = 1; i <= n; i++) {
            if(!dfn[i]) {
                targan(i);
            }
        }
        suo();
        if(topo()) {
            printf("Yes\n");
        }
        else {
            printf("No\n");
        }
    }
    return 0;
}

/*
11

8 10
1 5
6 3
2 7
7 8
3 6
8 2
2 1
4 6
7 3
6 5

5 8
1 2
2 3
3 4
1 3
1 4
2 4
4 5
5 4

6 10
6 3
2 5
4 6
3 6
2 6
6 1
1 5
3 2
4 1
5 3

7 8
1 2
3 1
3 2
2 4
4 7
4 5
5 6
6 4

3 3
1 2
2 3
3 1

5 5
1 2
2 3
3 1
3 4
4 5

4 4
1 2
2 3
3 1
4 3

4 4
1 2
1 3
2 4
3 4

3 3
1 2
2 1
3 1

4 4
1 2
1 3
2 4
3 4

4 5
1 2
2 3
2 4
1 3
1 4

No
Yes
Yes
Yes
Yes
Yes
Yes
No
Yes
No
No

*/


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