HDU 1269 迷宫城堡 (强联通分量,Tarjan算法)

Problem Description:

为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,,只说明可以通过这个通道由A房间到达B房间,但并不说明通过它可以由B房间到达A房间。Gardon需要请你写个程序确认一下是否任意两个房间都是相互连通的,即:对于任意的i和j,至少存在一条路径可以从房间i到房间j,也存在一条路径可以从房间j到房间i。

Input:

输入包含多组数据,输入的第一行有两个数:N和M,接下来的M行每行有两个数a和b,表示了一条通道可以从A房间来到B房间。文件最后以两个0结束。

Output:

对于输入的每组数据,如果任意两个房间都是相互连接的,输出"Yes",否则输出"No"。

Sample Input:

3 31 22 33 13 31 22 33 20 0

Sample Output:

YesNo

#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <cmath>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#define LL long longusing namespace std;const int MAXN = 10000 + 10;vector<int>G[MAXN];int pre[MAXN], lowlink[MAXN], sccno[MAXN], dfs_clock, scc_cnt;//scc_cnt为强联通分量计数器,sccno[i]表示节点i所在的强联通分量编号.stack<int>S;void dfs(int u){pre[u] = lowlink[u] = ++dfs_clock;S.push(u);for(int i=0;i<G[u].size();i++){int v = G[u][i];if(!pre[v]){dfs(v);lowlink[u] = min(lowlink[u], lowlink[v]);}else if(!sccno[v]){lowlink[u] = min(lowlink[u], pre[v]);}}if(lowlink[u] == pre[u]){scc_cnt++;for(;;){int x = S.top(); S.pop();sccno[x] = scc_cnt;if(x == u) break;}}}void Tarjan(int n){dfs_clock = scc_cnt = 0;memset(sccno, 0, sizeof(sccno));memset(pre, 0, sizeof(pre));for(int i=1;i<=n;i++)if(!pre[i]) dfs(i);}int main(){int n, m;while(scanf("%d%d", &n, &m)!=EOF){if(n == 0 && m == 0)break;int u, v;for(int i=0;i<=n;i++) G[i].clear();for(int i=0;i<m;i++){scanf("%d%d", &u, &v);G[u].push_back(v);}Tarjan(n); //若强联通分量个数为1则证明所有的点都是强联通的if(scc_cnt == 1) printf("Yes\n");else printf("No\n");}return 0;}

你写PPT时,阿拉斯加的鳕鱼正跃出水面,

HDU 1269 迷宫城堡 (强联通分量,Tarjan算法)

相关文章:

你感兴趣的文章:

标签云: