poj3177 - Redundant Paths-tarjan缩点+求度为1的点

把无向图的边双联通块缩成一个点,然后建立一棵树。

假如树中度数为1的点的个数为x个。

那么结果为(x+1)/2.

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define maxn 5500
#define maxm 22000
#define mem(a,b) (memset(a,b,sizeof(a)))
struct gra
{
    int n,m;
    struct list{int u,v,next;}edge[maxm];
    int head[maxn],num,vis[maxm];
    int dnf[maxn],low[maxn],times;
    int cnt[maxn];
    void init(int x,int y){
        num=0;times=1;
        n=x;m=y;
        mem(head,-1);mem(dnf,0);mem(low,0);
        mem(vis,0);mem(cnt,0);
    }
    void add(int u,int v){
        edge[num].u=u;edge[num].v=v;
        edge[num].next=head[u];head[u]=num++;
    }
    void tarjan(int x)
    {
        dnf[x]=low[x]=times++;
        for(int i=head[x];i!=-1;i=edge[i].next)
        {
            int y=edge[i].v;
            if(vis[i])continue;
            vis[i]=vis[i^1]=1;
            if(!dnf[y])
            {
                tarjan(y);
                low[x]=min(low[x],low[y]);
            }
            else
            {
                low[x]=min(low[x],dnf[y]);
            }
        }
    }
    void start()
    {
        tarjan(1);
        for(int x=1;x<=n;x++)
        {
            for(int i=head[x];i!=-1;i=edge[i].next)
            {
                int y=edge[i].v;
                if(low[x]!=low[y])
                {
                    cnt[low[y]]++;
                }
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            if(cnt[i]==1)ans++;
        }
        cout<<(ans+1)/2<<endl;
    }
}G;
int main()
{
    int n,m,i,a,b;
    while(~scanf("%d%d",&n,&m))
    {
        G.init(n,m);
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            G.add(a,b);
            G.add(b,a);
        }
        G.start();
    }
    return 0;
}
















你可能感兴趣的:(poj3177 - Redundant Paths-tarjan缩点+求度为1的点)