您的位置:首页 > 其它

HDU - 1269 - 迷宫城堡 (tarjan求强连通分量)

2015-08-04 10:47 288 查看
题目传送:迷宫城堡

思路:就是tarjan啦,不过korasaju肯定也行啦,这里注意可能本身就不是连通图

AC代码:

[code]#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define INF 0x7fffffff
using namespace std;

const int maxn = 10005;

int n, m;

vector<int> mp[maxn];

int dfn[maxn];
int low[maxn];
int index;

int cnt;//统计连通分量个数 
int sum;

int vis[maxn];

stack<int> s;
bool in_stack[maxn];

void tarjan(int u) {
    dfn[u] = low[u] = ++index;              // 为节点u设定次序编号和Low初值
    s.push(u);                              // 将节点u压入栈中
    sum ++;
    vis[u] = 1;
    in_stack[u] = true;

    int d = mp[u].size();
    for(int i = 0; i < d; i ++) {           // 枚举每一条边
        int v = mp[u][i];
        if(!vis[v]) {                       // 如果节点v未被访问过
            tarjan(v);                      // 继续向下找
            low[u] = min(low[u], low[v]);   //更新 
        }
        else if(in_stack[v]) {              // 如果节点v还在栈内
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(dfn[u] == low[u]) {                  // 如果节点u是强连通分量的根
        int v;
        do {
            v = s.top();                    // 将v退栈,为该强连通分量中一个顶点
            s.pop();
            in_stack[v] = false;
        } while(u != v);
        cnt ++;
    }

}

int main() {
    while(scanf("%d %d", &n, &m) != EOF) {
        if(n == 0 && m == 0) break;

        for(int i = 0; i <= n; i ++) {
            mp[i].clear();
        }

        int u, v;
        for(int i = 0; i < m; i ++) {
            scanf("%d %d", &u, &v);
            mp[u].push_back(v);
        }

        memset(in_stack, false, sizeof(in_stack));
        memset(vis, 0, sizeof(vis));
        while(!s.empty()) s.pop();
        cnt = 0;//统计强连通分量个数 
        index = 0;
        sum = 0;//居然可以是非连通图。。好吧。。连WA78次。。这个用来统计一个连通分量里的节点个数 

        tarjan(1);

        if(cnt == 1 && sum == n) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: