有向图的强联通分量Tarjan算法模版(hdu1269)
2015-07-19 22:03
429 查看
迷宫城堡
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 9341 Accepted Submission(s): 4170
[align=left]Problem Description[/align]
为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明可以通过这个通道由A房间到达B房间,但并不说明通过它可以由B房间到达A房间。Gardon需要请你写个程序确认一下是否任意两个房间都是相互连通的,即:对于任意的i和j,至少存在一条路径可以从房间i到房间j,也存在一条路径可以从房间j到房间i。
[align=left]Input[/align]
输入包含多组数据,输入的第一行有两个数:N和M,接下来的M行每行有两个数a和b,表示了一条通道可以从A房间来到B房间。文件最后以两个0结束。
[align=left]Output[/align]
对于输入的每组数据,如果任意两个房间都是相互连接的,输出"Yes",否则输出"No"。
[align=left]Sample Input[/align]
3 3 1 2 2 3 3 1 3 3 1 2 2 3 3 2 0 0
[align=left]Sample Output[/align]
Yes No
[align=left]Author[/align]
Gardon
[align=left]Source[/align]
HDU 2006-4 Programming Contest
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> using namespace std; const int maxn = 10010; const int maxm = 100010; struct Edge { int v,next; }edge[maxm]; //边结点数组 int first[maxn],stack[maxn],DFN[maxn],low[maxn],Belong[maxn]; /*first[]头结点数组,stack[]为栈,DFN[]为深搜次序数组, Belong[]为每个结点所对应的强连通数组,low[u]为u结点 或者u的子树结点所能追溯到最早栈中结点的次序号 */ int instack[maxn]; //instack[]为是否在栈中的标记数组 int n,m,cnt,scnt,top,tot; void init() { cnt = 0; scnt = top = tot = 0; //初始化连通分量标号,次序计数器,栈顶指针为0 memset(first,-1,sizeof(first)); memset(DFN,0,sizeof(DFN)); //结点搜索的次序编号数组为0,同时可以当是否访问的数组使用 } void read_graph(int u,int v) //构建邻接表 { edge[tot].v = v; edge[tot].next = first[u]; first[u] = tot++; //第几条边 } void Tarjan(int v) //Tarjan算法求有向图的强连通分量 { int min,t; DFN[v] = low[v] = ++tot; //tot为时间轴 instack[v] = 1; //标记在栈里 stack[top++] = v; //入栈 for(int e = first[v];e != -1;e = edge[e].next) //枚举v的每一条边 { int j = edge[e].v; //v所邻接的边 if(!DFN[j]) //未被访问 { Tarjan(j); //继续往下找 if(low[v] > low[j]) low[v] = low[j]; //更新结点v所能到达的最小次层数 } else if(instack[j] && DFN[j] < low[v]) { low[v] = DFN[j]; } } if(DFN[v] == low[v]) //如果结点v是强连通分量的根 { scnt++; //连通分量标号加1 do { t = stack[--top]; //退栈 instack[t] = 0; //标记不在栈中 Belong[t] = scnt; //出栈结点t属于cnt标号的强连通分量 }while(t != v); //直到将v从栈中退出 } } void solve() { for(int i=1;i<=n;i++) { if(!DFN[i]) //未被访问 Tarjan(i); //则找i结点的连通分量 } } int main() { //freopen("1.txt","r",stdin); while(cin>>n>>m && (n || m)) { init(); while(m--) { int u,v; cin>>u>>v; read_graph(u,v); } solve(); //求强连通分量 if(scnt == 1) cout<<"Yes"<<endl; else cout<<"No"<<endl; } return 0; }
相关文章推荐
- Centos Linux 开启端口 - 解决Centos发布服务外网访问不了的问题
- Hadoop2.6.0学习笔记(一)MapReduce介绍
- 软件开发工具
- CodeForces 399C Cards (数论)
- NSUnknownKeyException的原因
- 路由器,防火墙的角色
- Compound Words
- 我的Android进阶之旅------>Android嵌入图像InsetDrawable的用法
- 用D3.js进行医疗数据可视化 (一)折线图 (Line Chart)
- 精选30道Java笔试题解答
- 关于usr/bin/ld: cannot find -lxxx问题总结
- 在win32控制台应用程序中实现定时器
- Linux kernel 分析之一:内核镜像
- linux c 获取系统关机时间
- HDU1061Rightmost Digit题解
- 在ubuntu平台下完全开发smart210
- 关于能量谱、功率谱和时域信号
- Git版本控制:Git分支处理
- Git分支处理
- mysql数据库维护(备份和还原)和性能提高