POJ 3352 Road Construction (边双连通分量)
2014-09-19 10:43
543 查看
题目类型 边双连通分量
题目意思
给出一个 n 个点 m 条边的无向连通图(n,m<=1000) 问至少要添加多少条无向边使得 删除原图中任意一条边后原图依然连通
解题方法
根据题意 显然如果删除原图中的 桥 就会使原图不连通 那么首先把原图中的 边双连通分量看成一个点(即缩点) 然后点与点之间的边即为桥
则原问题转化成给出一棵若干个点的树问把树对应的图变为一个边双连通图最少需要添加多少条边
具体方法 -> Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)
结果为树的叶子结点数 + 1 再除 2
参考代码 - 有疑问的地方在下方留言 看到会尽快回复的
题目意思
给出一个 n 个点 m 条边的无向连通图(n,m<=1000) 问至少要添加多少条无向边使得 删除原图中任意一条边后原图依然连通
解题方法
根据题意 显然如果删除原图中的 桥 就会使原图不连通 那么首先把原图中的 边双连通分量看成一个点(即缩点) 然后点与点之间的边即为桥
则原问题转化成给出一棵若干个点的树问把树对应的图变为一个边双连通图最少需要添加多少条边
具体方法 -> Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)
结果为树的叶子结点数 + 1 再除 2
参考代码 - 有疑问的地方在下方留言 看到会尽快回复的
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <stack> using namespace std; const int maxn = 1000 + 10; struct Edge { int u, v; }; int pre[maxn], dfs_clock, bcc_cnt; int bcc[maxn], d[maxn]; int GG[maxn][2], n; bool g[maxn][maxn]; int dfs(int u, int fa) { int lowu = pre[u] = dfs_clock++; for( int i=0; i<n; i++ ) { if(g[u][i] == false) continue; int v = i; if(pre[v] == false) { int lowv = dfs(v, u); lowu = min(lowu, lowv); if(lowv > pre[u]) { g[u][v] = g[v][u] = false; } } else if(pre[v] < pre[u] && v != fa) { lowu = min(lowu, pre[v]); } } return lowu; } void find_cc() { // 用tarjan算法求出所有桥 memset(pre, 0, sizeof(pre)); dfs_clock = 0; for( int i=0; i<n; i++ ) { if(pre[i] == false) dfs(i, -1); } } void dfs(int u) { // 求不经过桥的连通分量 即边双连通分量 bcc[u] = bcc_cnt; for( int i=0; i<n; i++ ) { if(g[u][i] == false || bcc[i] != -1) continue; dfs(i); } } int main() { freopen("in", "r", stdin); int m; while(scanf("%d%d", &n, &m) != EOF) { memset(g, 0, sizeof(g)); for( int i=0; i<m; i++ ) { int u, v; scanf("%d%d", &u, &v); u--, v--; GG[i][0] = u, GG[i][1] = v; g[u][v] = g[v][u] = true; } find_cc(); bcc_cnt = 0; memset(bcc, -1, sizeof(bcc)); for( int i=0; i<n; i++ ) { if(bcc[i] == -1) dfs(i); bcc_cnt++; } memset(d, 0, sizeof(d)); for( int i=0; i<m; i++ ) { int u = GG[i][0], v = GG[i][1]; if(bcc[u] != bcc[v]) { d[bcc[u]]++; d[bcc[v]]++; } } int ans = 0; for( int i=0; i<bcc_cnt; i++ ) if(d[i] == 1) ans++; // 度数为1的点即为叶子结点 printf("%d\n", (ans+1)/2); } return 0; }
相关文章推荐
- POJ-3352 Road Construction 双连通分量
- POJ3352 Road Construction 双连通分量和桥 tarjan
- POJ3352 Road Construction 双连通分量和桥 tarjan
- poj 3352--Road Construction(双连通分量)
- POJ 3352 Road Construction 构造双连通分量 && POJ 3177Redundant Paths注意重边
- POJ 3352 Road Construction (边双连通分量)
- Road Construction POJ - 3352 (边双连通分量)题解
- poj 3352 Road Construction(点双连通分量缩点+缩点树变为双连通分量)
- POJ 3352 Road Construction (边双连通分量 Tarjan缩点)
- POJ 3177 Redundant Paths & POJ 3352 Road Construction(双连通分量)
- poj3352——Road Construction(双连通分量)
- Tarjan算法求解桥和边双连通分量(附POJ 3352 Road Construction解题报告
- POJ 3177 / POJ 3352 : Redundant Paths / Road Construction - 边双连通分量,缩点
- poj 3352 Road Construction(边-双连通分量)
- POJ 3352 Road Construction【双连通分量_桥】
- POJ 3352 Road Construction / 边双连通分量
- POJ-3352 Road Construction (边双连通分量[Tarjan])
- POJ 3352 Road Construction(边双连通分量,桥,tarjan)
- Tarjan算法求解桥和边双连通分量(附POJ 3352 Road Construction解题报告)
- poj 3352 Road Construction 边双连通分量