POJ 3177 Redundant Paths (边双连通,缩点,判重)

来源:互联网 发布:淘宝怎么转接人工客服 编辑:程序博客网 时间:2024/05/14 01:48

题意:加上最少的边,使得改造后的图中去掉任意一条边后图依然连通。(图是非简单图,需要判重)
题解:先找出边双连通分量,然后缩点,的到一棵树。需要加的最少边=(leaves+1)/2

我们可以发现low[4]=3,low[7]=4 但是我们知道<4,7>这条边并不是割边.所以low[u]!=low[v]是割边的必要不充分条件.

#include <iostream>using namespace std;#define N 10010#define min(a,b) (a<b?a:b)int f, r;int size, id, top, scc;int instack[N], stack[N];int dfn[N], low[N], block[N];int head[N], degree[N];struct { int v, next; } edge[N*2];void add ( int u, int v ){size++;edge[size].v = v;edge[size].next = head[u];head[u] = size;}bool judge ( int u, int father )  // 判断是否有重边{int repeat = 0;for ( int i = head[u]; i; i = edge[i].next )if ( edge[i].v == father ) repeat++;if ( repeat >= 2 ) return true;return false;}void Tarjan ( int u, int father ){int v, t;stack[++top] = u;instack[u] = 1;dfn[u] = low[u] = ++id;bool repeat = judge ( u, father );for ( int i = head[u]; i; i = edge[i].next ){v = edge[i].v;if ( v == father && ! repeat ) continue;if ( ! dfn[v] ){Tarjan ( v, u );low[u] = min ( low[u], low[v] );if ( low[v] > dfn[u] ){scc++;do {t = stack[top--];instack[t] = 0;block[t] = scc;} while ( t != v );}}else if ( instack[v] )low[u] = min ( low[u], dfn[v] );}}int shrink (){int u, v, i, leaves = 0;for ( u = 1; u <= f; u++ ){for ( i = head[u]; i; i = edge[i].next ){v = edge[i].v;if ( block[u] != block[v] ){degree[block[u]]++;degree[block[v]]++;}}}for ( i = 0; i <= scc; i++ )if ( degree[i] == 2 ) leaves++;return (leaves+1)/2;}void initial (){size = scc = top = id = 0;for ( int i = 0; i <= f; i++ ){dfn[i] = head[i] = instack[i] = 0;low[i] = degree[i] = block[i] = 0;}}int main(){int u, v;while ( scanf("%d%d",&f,&r) != EOF ){initial();while ( r-- ){scanf("%d%d",&u,&v);add ( u, v );add ( v, u );}for ( int i = 1; i <= f; i++ )if ( ! dfn[i] ) Tarjan ( i, f+1 );printf("%d\n",shrink());}return 0;}


原创粉丝点击