您的位置:首页 > 其它

Redundant Paths POJ, 3177

2016-04-14 23:30 417 查看
//并查集加桥

//注意有重边的情况,对edge进行处理

#include<cstdio>

#include<cstdlib>

#include<vector>

#include<cstring>

#include <climits>

#include <list>

#include <set>

#define MAXN 5005

#define maxn 10005

using  namespace std;

int parent[MAXN];//每个节点的父亲

int dfn[MAXN];

int low[MAXN];

typedef struct{

    int  to;

    int next;

}Edge;

Edge edge[maxn];

int  head[MAXN];

int judge[MAXN];

int  visit[MAXN];

list<pair<int ,int > >bridge;

set<int>S;

int ans,edge_sum;

void  addedge(int s,int t)

{

    edge[edge_sum].to=t;

    edge[edge_sum].next=head[s];

    head[s]=edge_sum++;

}

//并查集

int findP(int x)

{

    return x==parent[x] ? x :findP(parent[x]);

}

void Tunion(int u,int v)

{

    int i=findP(u),j=findP(v);

    if(i!=j)parent[v]=u;

}

//dfs

void dfs(int u,int p)

{

    //记录dfs遍历次序

    static int counter = 0;

    //记录节点u的子树数

    int i=head[u];

    dfn[u] = low[u] = ++counter;

    visit[u]=1;

    memset(judge,0,sizeof(judge));//特殊处理

    for(; i!=-1; i=edge[i].next) {

        int v = edge[i].to;

        judge[v]++;

        //节点v未被访问,则(u,v)为树边

        if(!visit[v]) {

            dfs(v,u);

            low[u] = min(low[u], low[v]);

            if(low[v]>dfn[u])//

                {

                bridge.push_back(make_pair(u,v));

            }

            else

            {

                Tunion(u,v);

            }

        }

        //节点v已访问,则(u,v)为回边

        else if(v != p||judge[v]>=2)//u被访问次数大于2次

            {

            low[u] = min(low[u], dfn[v]);

            judge[v]=0;   //将其清零

        }

    }

}

int main()

{

    int N,M;

    while(~scanf("%d%d",&N,&M))

    {

        bridge.clear();

        S.clear();

        ans=0;

        edge_sum=0;

        memset(head,-1,sizeof(head));

        for(int i=0;i<N;i++)

            parent[i]=i;

        memset(dfn,0,sizeof(dfn));

        memset(low,0,sizeof(low));

        memset(visit,0,sizeof(visit));

        int k1,k2;//表示两个顶之间有边

        for(int i=0;i<M;i++)

        {

            scanf("%d%d",&k1,&k2);

            k1--,k2--;

            addedge(k1,k2);

            addedge(k2,k1);

        }

        if(N==1){printf("%d\n",0);continue;}

        else

        {

        dfs(0,0);

        edge_sum=0;

        memset(head,-1,sizeof(head));

        for(list<pair<int ,int > >::iterator it=bridge.begin();it!=bridge.end();it++)

            {

           //printf("%d %d\n",findP(it->first),findP(it->second));

             S.insert(findP(it->first));

             S.insert(findP(it->second));

             addedge(findP(it->first),findP(it->second));

             addedge(findP(it->second),findP(it->first));

            }

        for(set<int>::iterator it=S.begin();it!=S.end();it++)

        {

            int t=*it;

            //printf("T:%d\n",t);

          //printf("%d %d\n",head[t],edge[head[t]].next);

            if(head[t]!=-1&&edge[head[t]].next==-1)//度为1

                ans++;

        }

        printf("%d\n",(ans+1)/2);

        }

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: