您的位置:首页 > 其它

POJ 3177 - Redundant Paths 无向图变边双联通加几条边

2017-10-03 20:36 393 查看
无向图和有向图其实没啥区别...

缩完点之后就变成一个树了。

我们把树中度为1的点都连起来即可。

(ans+1)/2

#include<cstdio>

#include<stack>

using namespace std;

#define N 5005

struct node{

    int v,next;

}e[N<<1];

int n,m,tot,head
,low
,dfn
,id
,in
,pd,sd;

bool mark
,mp

;

stack<int>s;

void add(int x,int y){//判断是不是父边 

    e[++tot].v=y;

    e[tot].next=head[x];

    head[x]=tot;

}

bool judge(int x,int y){

    if((x&1)&&y==x+1) return 1;

    if(!(x&1)&&y==x-1) return 1;

    return 0;

}

void tarjan(int v,int fa){

    low[v]=dfn[v]=++pd;

    s.push(v);

    mark[v]=1;

    for(int i=head[v];i;i=e[i].next){

        if(judge(i,fa)) continue;

        int w=e[i].v;

        if(!dfn[w]){

            tarjan(w,i);

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

        }

        else if(mark[w]){

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

        }

    }

    int u;

    if(low[v]==dfn[v]){

        sd++;

        do{

            u=s.top();

            s.pop();

            id[u]=sd;

            mark[u]=0;

        }while(u!=v);

    }

}

int main(){ 

    scanf("%d%d",&n,&m);

    for(int i=1,x,y;i<=m;i++){

         scanf("%d%d",&x,&y);

         if(!mp[x][y]){

             add(x,y);add(y,x);

             mp[x][y]=mp[y][x]=1;

         }

    }

    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,-1);

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

        for(int j=head[i];j;j=e[j].next){

            if(id[i]!=id[e[j].v]){

                in[id[i]]++;

            }

        }

    }

    int ans=0;

    for(int i=1;i<=sd;i++) if(in[i]==1) ans++;

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

    return 0;

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