题目传送:迷宫城堡
思路:就是tarjan啦,不过korasaju肯定也行啦,这里注意可能本身就不是连通图
AC代码:
#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;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU - 1269 - 迷宫城堡 (tarjan求强连通分量)
原文地址:http://blog.csdn.net/u014355480/article/details/47273525