poj 3177 缩点,双连通分量
算法:
就是给你一个无向图,至少添加几条边,使得从fieldsi 到fields j的路径至少有两条以上。
转化为问题:
添加几条边使得图变成双连通图。。
方法:
1.用tarjian算法缩点。。
2.根据公式计算。。
若要使得任意一棵树,在增加若干条边后,变成一个双连通图,那么
至少增加的边数 =( 这棵树总度数为1的结点数 + 1 )/ 2
来自:http://blog.csdn.net/lyy289065406/article/details/6762370
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> #include<vector> #include<string> #include<math.h> #include<map> #include<set> #include<stack> #include<algorithm> using namespace std; #define MAXN 100010 struct Edge { int v, next; Edge() { } Edge( int V, int Next): v(V), next(Next) {} }edge[MAXN]; int head[MAXN],d[MAXN], low[MAXN], visit[MAXN],degree[MAXN], e, F, R, ptime, cnt; stack<int>p; void init( ) { e = 0; ptime = 0; cnt = 0; memset(head, -1, sizeof(head)); memset(d, 0, sizeof(d)); memset(low, 0, sizeof(low)); memset(visit,0,sizeof(visit)); memset(degree,0,sizeof(degree)); } int jugde( int u, int v) { for( int e = head[u]; e != -1; e = edge[e].next) { if( edge[e].v == v ) return 1; } return 0; } void AddEdge( int u, int v) { if( jugde(u,v) ) return; edge[e] = Edge(v, head[u]); head[u] = e++; edge[e] = Edge(u, head[v]); head[v] = e++; } void tarjian(int u, int pf) { d[u] = low[u] = ++ptime; for( int e = head[u]; e != -1; e = edge[e].next) { int v = edge[e].v; if( v == pf ) continue; if( !d[v] ) { tarjian(v, u); low[u] = min(low[u], low[v]); } else { low[u] = min(low[u], d[v]); } } } int solve( ) { for( int i = 1; i <= F; i++) { for( int e = head[i]; e != -1; e = edge[e].next) { int v = edge[e].v; if( low[i] != low[v] ) { degree[low[i]]++; degree[low[v]]++; } } } int cnt = 0; for( int i = 0; i <= ptime; i++) { if( degree[i] / 2 == 1 ) cnt++; } return (cnt + 1) / 2; } int main( ) { int a, b; while( scanf("%d%d", &F, &R) != EOF) { init( ); for( int i = 1; i <= R; i++) { scanf("%d%d",&a,&b); AddEdge(a, b); } for( int i = 1; i <= F; i++) { if( !d[i] ) tarjian( i , i); } printf("%d\n",solve( )); } return 0; }
posted on 2012-09-24 18:32 more think, more gains 阅读(200) 评论(0) 编辑 收藏 举报