POJ 1515 Street Directions 边双连通分量 + dfs
2016-05-02 19:30
417 查看
题目:http://poj.org/problem?id=1515
题意:给定一个无向连通图,对图中的尽量多的边定为单向边,使之成为一个强连通图,对于无法定成单向边的,就定为双向边
思路:显然,对图进行边双连通分量分解,其中桥一定定为双向边,否则必然不是强连通图,对于其他边,因为是连通分量内的边,必然成环,按dfs遍历输出就好,必定构成强连通图
题意:给定一个无向连通图,对图中的尽量多的边定为单向边,使之成为一个强连通图,对于无法定成单向边的,就定为双向边
思路:显然,对图进行边双连通分量分解,其中桥一定定为双向边,否则必然不是强连通图,对于其他边,因为是连通分量内的边,必然成环,按dfs遍历输出就好,必定构成强连通图
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int N = 1010; struct edge { int to, next; } G[N*100]; int dfn , low , head , st , dcc ; int index, num, cnt, top; int n, m, x = 0; bool vis , visnode , visedge[N*100]; void init() { memset(dfn, -1, sizeof dfn); memset(head, -1, sizeof head); memset(vis, 0, sizeof vis); memset(visnode, 0, sizeof visnode);/*标记顶点*/ memset(visedge, 0, sizeof visedge);/*标记边*/ index = num = cnt = top = 0; } void add_edge(int v, int u) { G[cnt].to = u; G[cnt].next = head[v]; head[v] = cnt++; } bool judge(int v, int fa) { int tmp = 0; for(int i = head[v]; i != -1; i = G[i].next) if(G[i].to == fa) tmp++; if(tmp >= 2) return true; else return false; } void tarjan(int v, int fa) { dfn[v] = low[v] = index++; vis[v] = true; st[top++] = v; bool f = judge(v, fa); int u, t; for(int i = head[v]; i != -1; i = G[i].next) { u = G[i].to; if(u == fa && !f) continue; if(dfn[u] == -1) { tarjan(u, v); low[v] = min(low[v], low[u]); } else if(vis[u]) low[v] = min(low[v], dfn[u]); } if(dfn[v] == low[v]) /*v不能连到祖先,必为连通分量的根*/ { num++; do { t = st[--top]; dcc[t] = num; vis[t] = false; } while(t != v); } } void dfs(int v, int fa) { visnode[v] = true; for(int i = head[v]; i != -1; i = G[i].next) { int u = G[i].to; if(u == fa) continue; if(dcc[v] == dcc[u] && visedge[i] == false) /*同一个边连通分量内,定为单向边*/ { printf("%d %d\n", v, u); } else if(dcc[v] != dcc[u] && visedge[i] == false) /*边(v,u)为桥,双向边*/ { printf("%d %d\n", v, u); printf("%d %d\n", u, v); } visedge[i] = true; /*无向图,所以标记两次*/ visedge[i^1] = true; if(! visnode[u]) dfs(u, v); } } void slove() { printf("%d\n\n", ++x); tarjan(1, -1); dfs(1, -1); printf("#\n"); } int main () { int a, b; while(scanf("%d%d", &n, &m), n || m) { init(); for(int i = 0; i < m; i++) { scanf("%d%d", &a, &b); add_edge(a, b); add_edge(b, a); } slove(); } return 0; }
相关文章推荐
- 第八周-类和指针
- 阶段性总结(2016.夏)
- 191.[Leetcode]Number of 1 Bits
- C++实现简单的HTTP服务器
- python中的可变参数
- 序列化流的使用
- 百度地图定位
- 第十周 5.2 --- 5.8
- Docke开山篇
- [BZOJ2440][中山市选2011]完全平方数(二分+容斥原理)
- NYOJ99单词拼接(欧拉通路回路,dfs打印路径)
- leetcode 073 Set Matrix Zeroes
- XML的解析
- 快速点击两次退出应用
- Just a Hook---hdu1698(线段树---区间处理)
- iOS App icon、启动页、图标规范
- 【操作系统】OS的整体框架
- hiho#1050 : 树中的最长路
- c语言学生信息管理系统学习感想
- 如何成为一个牛逼的C/C++程序员?