[边双连通分量] poj 3177 Redundant Paths
来源:互联网 发布:smash it up bgm 编辑:程序博客网 时间:2024/05/17 06:13
/**[边双连通分量] poj 3177 Redundant Paths题目同poj 3352.求至少添加几条边形成边双连通图,区别在于这里输入时要过滤掉重边。1,tarjan 2,缩点建树 3,求叶子结点数目nlef return (nlef + 1) / 2*/#include <stdio.h>#include <string.h>#include <vector>#include <algorithm>using namespace std;#define N 5005bool mb[N][N];int low[N],vis[N],dfn[N],tim;vector<int> g[N];int n,m;void dfs(int u,int f){ vis[u] = 1; low[u] = dfn[u] = ++tim; for(int i = 0; i < g[u].size(); ++i) { int v = g[u][i]; if(v != f && vis[v] == 1) low[u] = min(low[u],dfn[v]); if(vis[v] == 0) { dfs(v,u); low[u] = min(low[u],low[v]); } } vis[u] = 2;}int minAdd(){ memset(vis,0,sizeof(vis)); tim = 0; dfs(1,0); int i,j,k,deg[N] = {0}; for(i = 1; i <= n; ++i) for(j = 0; j < g[i].size(); ++j) { k = g[i][j]; if(low[i] != low[k]) deg[low[i]] ++; } int num = 0; for(i = 1; i <= n; ++i) if(deg[i] == 1) ++num; return (num + 1) / 2;}int main(){ int a,b; scanf("%d%d",&n,&m); while(m --) { scanf("%d%d",&a,&b); if(mb[a][b]) continue; mb[a][b] = mb[b][a] = 1; g[a].push_back(b); g[b].push_back(a); } printf("%d\n",minAdd()); return 0;}