Tarjan模板题。建议采用二维vector存储。
学习Tarjan时要注意两个数组:
int DFN[M]; //深度优先搜索访问次序
int Low[M]; //能追溯到的最早的次序
这是学习的网址:http://www.nocow.cn/index.php/Tarjan算法
P.s. Tarjan真心是递归之精髓的体现啊!
下面是标准的Tarjan的模板。
这道题算法其实很清楚,把图的边反向存储,再把图的强连通分量求出来,然后找出入度为零的分量,如果入度为0的强连通分量个数大于1,那么最终解一定是0,否则最终解就是那个入度为零的强连通分量的点的个数。
#include <iostream> #include <string.h> #include <vector> #define MAX_N 10010 #define MAX_M 50010 using namespace std; vector <int> vec[MAX_N]; int dfn[MAX_N], low[MAX_N], stap[MAX_N], belong[MAX_N]; int n, m, bcnt, dindex = 0, stop = 0; int rd[MAX_N], rd0cnt; bool instack[MAX_N]; int x[MAX_M], y[MAX_M]; void tarjan(int v) { int u, l = vec[v].size(); dfn[v] = low[v] = ++dindex; instack[v] = true; stap[++stop] = v; for (int i = 0; i < l; i++) { u = vec[v][i]; if (!dfn[u]) { tarjan(u); if (low[u] < low[v]) low[v] = low[u]; } else if (instack[u] && dfn[u] < low[v]) low[v] = dfn[u]; } if (dfn[v] == low[v]) { bcnt++; do { u = stap[stop--]; instack[u] = false; belong[u] = bcnt; } while (u != v); } } int main() { while (cin >> n >> m) { for (int i = 1; i <= m; i++) { cin >> x[i] >> y[i]; vec[y[i]].push_back(x[i]); } stop = bcnt = dindex = 0; memset(dfn, 0, sizeof(dfn)); for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i); memset(rd, 0, sizeof(rd)); for (int i = 1; i <= m; i++) if (belong[x[i]] != belong[y[i]]) rd[belong[x[i]]]++; int cnt = 0; for (int i = 1; i <= bcnt; i++) if (rd[i] == 0) cnt++; if (cnt > 1) cout << 0 << endl; else { cnt = 0; for (int i = 1; i <= n; i++) if (rd[belong[i]] == 0) cnt++; cout << cnt << endl; } } }
原文:http://blog.csdn.net/zhengnanlee/article/details/21274877