HDU 3394 Railway 点双连通分量 + 桥
2016-05-02 11:36
573 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3394
题意:给一个无向图。如果至少有两个环共用了一些边,那么这些边被认为是“冲突边”。如果一些边不在任何一个环中,这些边被认为是“多余边”。你要找出这个图中有多少“多余边”和“冲突边”然后输出条数。另外这图不一定是连通的
思路:不需要的路肯定是桥,很好统计。对于冲突边,我以为按边双连通分量找,结果哇了,百度了一下,按照点双连通分量找,,,因为边双连通分量中任意两点之间虽然存在至少两条路径,但如果有公共顶点(边双连通允许有公共顶点),那么就不符合环的定义(当且仅且起点与终点相同),故应当找点双连通分量,另外一个理解是找边双连通分量无法判断一个连通分量内的环是否冲突(我感觉这种说法更靠谱一些),比如:
10 13
1 2
1 3
2 3
3 4
4 5
4 6
5 6
4 7
4 8
7 8
4 9
4 10
9 10
总之,找出块中边数大于点数的,那么这个块中的边都是冲突边
总结:对于双连通分量是懵逼的。。。
题意:给一个无向图。如果至少有两个环共用了一些边,那么这些边被认为是“冲突边”。如果一些边不在任何一个环中,这些边被认为是“多余边”。你要找出这个图中有多少“多余边”和“冲突边”然后输出条数。另外这图不一定是连通的
思路:不需要的路肯定是桥,很好统计。对于冲突边,我以为按边双连通分量找,结果哇了,百度了一下,按照点双连通分量找,,,因为边双连通分量中任意两点之间虽然存在至少两条路径,但如果有公共顶点(边双连通允许有公共顶点),那么就不符合环的定义(当且仅且起点与终点相同),故应当找点双连通分量,另外一个理解是找边双连通分量无法判断一个连通分量内的环是否冲突(我感觉这种说法更靠谱一些),比如:
10 13
1 2
1 3
2 3
3 4
4 5
4 6
5 6
4 7
4 8
7 8
4 9
4 10
9 10
总之,找出块中边数大于点数的,那么这个块中的边都是冲突边
总结:对于双连通分量是懵逼的。。。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int N = 10010; struct edge { int to, next; } G[N*40]; int dfn , low , head , st ; int index, num, cnt, top; int n, m, res, ans; bool vis ; vector<int> dcc; void init() { memset(dfn, -1, sizeof dfn); memset(head, -1, sizeof head); memset(vis, 0, sizeof vis); index = num = cnt = top = 0; res = ans = 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 judge() { int indcc ; int tmp = 0; memset(indcc, 0, sizeof indcc); int len = dcc.size(); for(int i = 0; i < len; i++) indcc[dcc[i]] = 1; for(int i = 0; i < len; i++) for(int j = head[dcc[i]]; j != -1; j = G[j].next) if(indcc[G[j].to]) tmp++; tmp /= 2; if(tmp > len) ans += tmp; } 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]); if(dfn[v] < low[u]) res++; if(dfn[v] <= low[u]) { dcc.clear(); /*清空*/ do { t = st[--top]; vis[t] = false; dcc.push_back(t); }while(t != u); dcc.push_back(v); /*v可能也属于其他点连通分量,要加入但不能弹出*/ judge(); } } else if(vis[u]) low[v] = min(low[v], dfn[u]); } } void slove() { for(int i = 0; i < n; i++) if(dfn[i] == -1) tarjan(i, -1); printf("%d %d\n", res, ans); } 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; }
相关文章推荐
- Rails,ACM/ICPC CERC 1997,UVa514
- Insufficient memory<failed to allocate 232852> in cv::OutOfMemoryError
- LeetCode 217. Contains Duplicate
- codeforces 667A A. Pouring Rain(水题)
- poj2010 Moo University - Financial Aid(最大化第k大)
- leetcode 070 climbing stairs
- Coremail手机版页面持久型XSS实践
- kali无线渗透之Aireplay-ng小谈
- launch failed.Binary not found
- hdu 1021 Fibonacci Again
- CSU oj 1685 Entertainment Box
- 软件设计模式——责任链模式(Chain Of Responsibility)
- foxmail wine
- 解决nginx: [error] open() "/usr/local/var/run/nginx.pid" failed错误
- kali无线渗透之aireplay-ng
- Canvas和Paint的常用方法
- pair的用法
- 设计模式:责任链模式(Chain of Responsibility)
- 【CodeForces】A. Pouring Rain
- POJ 3714(Raid-平面最近点对)