[边双连通分量] 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;}