http://acm.hdu.edu.cn/showproblem.php?pid=1269
Tarjan的强连通算法:
对于每一个点有一个编号DFN和能往上一步的最小点的编号LOW
在进行深搜时,对于每一个节点都有一个编号
假定现在定点为u
深搜时有两种情况
1.v没有被搜过,继续搜,LOW[u] = min(LOW[u], LOW[v])(这是深搜v之后的结果)
2.v搜过了,LOW[u] = min(LOW[u], DFN[v])(注意这里的LOW定义的是上一个的编号,并不是一直能往上的最小的编号,当然也可以定义别的。。。)
用一个栈来维护是否这个v仍旧在这个图里面
实现:
/************************************************ * Author :Powatr * Created Time :2015/9/9 18:01:35 * File Name :LCA_BY_TARGAN.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int MAXN = 1e5 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; int LOW[MAXN], DFN[MAXN]; vector<int> G[MAXN]; int Stack[MAXN]; int vis[MAXN]; bool vis_stack[MAXN]; int index, group, coutt; void Tarjan(int u) { Stack[++coutt] = u; vis_stack[u] = true; LOW[u] = DFN[u] = ++index; int size = G[u].size(); for(int i = 0; i < size; i++){ int v = G[u][i]; if(!vis[v]){ vis[v] = 1; Tarjan(v); LOW[u] = min(LOW[u], LOW[v]); } else { if(vis_stack[v] == true) LOW[u] = min(LOW[u], DFN[v]); } } if(DFN[u] == LOW[u]){ group++; int uu; do{ uu = Stack[coutt--]; vis_stack[uu] = false; }while(uu != u); } } int main(){ int N, M, a, b; while(~scanf("%d%d", &N, &M) && (N + M)){//(N+M)要不是看了discussWA到死~~ index = coutt = group = 0; for(int i = 1; i <= N; i++){ G[i].clear(); Stack[i] = vis[i] = 0; vis_stack[i] = false; } for(int i = 1; i <= M; i++){ scanf("%d%d", &a, &b); G[a].push_back(b); } int cout_block = 0; for(int i = 1; i <= N; i++){ if(!vis[i]){ vis[i] = 1; cout_block++; if(cout_block >= 2) {group = 2; break;} Tarjan(i); } } printf("%s ", group > 1 ? "No" : "Yes"); } return 0; }