【边双连通 && 加几条边变成边双连通】POJ - 3177 Redundant Paths
2017-09-18 11:34
411 查看
Problem Description
输入n个点,m条边,边有重复,问你最少添加几条边,可以使得任意两个点,至少有两条不同的路径到达。其实就是问你最少添加几条边,使得图变成边双连通这里重边的意思是,1-2 1-2出现了两次,只算一次
思路:
卡了挺久的,就因为有重边,还以为是自己的代码错误。求边双连通的姿势不对。既然有重边,缩点(边双连通缩点)后 判断度得思考思考,有两种方法,一种是用邻接矩阵存边,这样重边就没事了,第二种方法就是,有桥就代表桥的两个端点肯定各自属于各自的边双连通,这时候我们记录下来那个点到那个点是桥,,最少添加边数为缩点后(叶子结点数+1)/2;
输入n个点,m条边,边有重复,问你最少添加几条边,可以使得任意两个点,至少有两条不同的路径到达。其实就是问你最少添加几条边,使得图变成边双连通这里重边的意思是,1-2 1-2出现了两次,只算一次
思路:
卡了挺久的,就因为有重边,还以为是自己的代码错误。求边双连通的姿势不对。既然有重边,缩点(边双连通缩点)后 判断度得思考思考,有两种方法,一种是用邻接矩阵存边,这样重边就没事了,第二种方法就是,有桥就代表桥的两个端点肯定各自属于各自的边双连通,这时候我们记录下来那个点到那个点是桥,,最少添加边数为缩点后(叶子结点数+1)/2;
#include<cstdio> #include<algorithm> #include<cstring> usi 4000 ng namespace std; #define mm 10055 struct node { int to, next; }; node Map[2 * mm];//存边 int n;//有多少个点 int head[mm], low[mm], dfn[mm], vis[mm], Stack[mm], top, N, sig; //vis[i]用来存i属于那个边双连通,N代表有几个边双连通 int d[mm]; node MAP[mm]; int cc; void add(int u, int v, int &cnt)//前向星存边 { Map[cnt].to = v; Map[cnt].next = head[u]; head[u] = cnt++; } void tardfs(int u, int father) { low[u] = dfn[u] = sig++; Stack[top++] = u; for(int i = head[u]; ~i; i = Map[i].next) { int to = Map[i].to; if(!dfn[to]) { tardfs(to, u); low[u] = min(low[u], low[to]); if(low[to] > dfn[u])//割边,记录桥的左右端点,为了后面求度所需 { MAP[cc++] = (node){u, to}; } } else if(!vis[to] && to != father) { low[u] = min(dfn[to], low[u]); } } /* printf("%d %d %d\n", u, low[u], dfn[u]);*/ if(low[u] == dfn[u])//缩点 { N++; do { int t = Stack[top - 1]; vis[t] = N; top--; }while(Stack[top] != u); } } void tarjan() { top = 0, N = 0, sig = 1; memset(vis, 0, sizeof(vis)); for(int i = 1; i <= n; i++) { if(!vis[i]) { tardfs(i, i); } } } int main() { int m, i, u, v; while(~scanf("%d %d", &n, &m)) { int cnt = 0; memset(head, -1, sizeof(head)); memset(MAP, 0, sizeof(MAP));//用来存桥的左右端点 for(i = 0; i < m; i++) { scanf("%d %d", &u, &v); add(u, v, cnt); add(v, u, cnt); } cc = 0; tarjan(); memset(d, 0, sizeof(d)); for(i = 0; i < cc; i++) { u = MAP[i].to, v = MAP[i].next; if(vis[u] != vis[v])//求度 { d[vis[u]]++; d[vis[v]]++; } } int ans = 0; for(i = 1; i <= N; i++) { if(d[i] == 1) ans++;//叶子节点 } printf("%d\n", (ans + 1) / 2);//最少添加边的个数 } return 0; }
相关文章推荐
- POJ 3177--Redundant Paths【无向图增加最少的边成为边双连通图 && tarjan求ebc && 缩点构造缩点树】
- POJ 3177--Redundant Paths【无向图添加最少的边成为边双连通图 && tarjan求ebc && 缩点构造缩点树】
- poj 3177 Redundant Paths【求最少添加多少条边可以使图变成双连通图】【缩点后求入度为1的点个数】
- 【连通图|边双连通+缩点】POJ-3177 Redundant Paths
- poj 3177 Redundant Paths(构造边双连通)
- POJ 3177 - Redundant Paths 无向图变边双联通加几条边
- POJ 3352 Road Construction&& POJ 3177 Redundant Paths 双联通分量
- POJ 3177 Redundant Paths 边双连通分支
- POJ 3177 Redundant Paths (双连通)
- POJ 3177 Redundant Paths(边连通分量)
- poj 3177 Redundant Paths 边双连通
- POJ - 3177 Redundant Paths (边双连通 tarjan)
- poj 3352 Road Construction【边双连通求最少加多少条边使图双连通&&缩点】
- poj 3177 Redundant Paths(求最少加几条边将图变为边双连通图)
- poj 3177 Redundant Paths (双连通)
- POJ 1236--Network of Schools【scc缩点构图 && 求scc入度为0的个数 && 求最少加几条边使图变成强联通】
- 【强连通分量模板题 && 加几条边变强连通】POJ - 1236 Network of Schools
- poj 3177 Redundant Paths 边双连通
- poj 3177 Redundant Paths 边双连通
- POJ 3352--Road Construction【无向图增加最少的边成为边双连通图 && tarjan求ebc && 缩点构造缩点树】