Tarjan算法--求割边(含重边) poj 3177

题目链接:http://poj.org/problem?id=3177

/*
    求割边: 将整个图进行缩点,然后再查找缩点后的图,即使一棵树
    求树中的叶子的个数n,那么就有(n+1)/2条边 为桥 
*/
# include 
# include 
# include 
# include 
# include 
# define MAXN 6000
using namespace std;

int dfn[MAXN],low[MAXN],degree[MAXN],belong[MAXN];
vector<int > vt[MAXN];
stack<int > stk;
int n,m,indx,num;

void init()
{
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(degree,0,sizeof(degree));
    memset(belong,0,sizeof(belong));

    indx = num = 0;
    for(int i=0; i<=n; ++i)
        vt[i].clear();
}

void Tarjan(int u,int fa)
{
    dfn[u] = low[u] = ++indx;
    stk.push(u);
    int flg = 0;
    for(int i=0; iint v = vt[u][i];
        if(!flg && v == fa)
        {
            flg = 1;
            continue;
        }
        if(!dfn[v])
        {
            Tarjan(v,u);
            low[u] = min(low[u],low[v]);
        }
        else
            low[u] = min(low[u],dfn[v]);
    }

    if(low[u] == dfn[u])
    {
        num++;
        int v;
        do
        {
            v = stk.top();
            stk.pop();
            belong[v] = num;
        }while(u != v);
    }
}


int main(void)
{
//  freopen("in.txt","r",stdin);
    while(cin >> n >> m)
    {
        init();
        for(int i=0; iint a,b;
            cin >> a >> b;
            vt[a].push_back(b);
            vt[b].push_back(a);
        }

        for(int i=1; i<=n; ++i)
        {
            if(!dfn[i])
                Tarjan(i,i);
        }

        int ans = 0;
        for(int i=1; i<=n; ++i)
        {

            for(int j=0; jint v = vt[i][j];
                if(belong[i] != belong[v])//缩点 
                    degree[belong[i]]++;
            }
        }
        for(int i=1; i<=n; ++i)//统计度数为一的点 
            if(degree[i] == 1)
                ans++;
        cout << (ans + 1)/2<return 0;
}

你可能感兴趣的:(图论)