POJ - 1515 Street Directions (无向图删边改使之变为强连通)

题意:

给出一个无向图,将某些无向边改造为单向边,使图变为强连通

分析:

将割边保留,双联通分量中的边改为单向边即可。

/*
    无向图转化为有向图
    保证图的连通性
*/

#include<cstdio>
#include<cstring>

using namespace std;

const int maxn=1e3+10;

struct node{
    int to;
    int nxt;
    int flag;
}edge[maxn*maxn];

int low[maxn],dfn[maxn];

int index;
int head[maxn],tot;

void addedge(int u,int v){
    edge[tot].to=v;
    edge[tot].nxt=head[u];
    edge[tot].flag=-1;
    head[u]=tot++;
}

void init(){
    memset(head,-1,sizeof head);
    memset(dfn,0,sizeof dfn);
    index=tot=0;
}

void tarjan(int u,int pre){
    int v;
    low[u]=dfn[u]=++index;
    for(int i=head[u];i!=-1;i=edge[i].nxt){
        v=edge[i].to;
        if(v==pre) continue;
        if(edge[i].flag!=-1) continue;          //注意这,如果是个双联通分量,不continue的话,会改变方向。
        edge[i].flag=1;
        edge[i^1].flag=0;
        if(!dfn[v]){
            tarjan(v,u);
            if(low[u]>low[v]){
                low[u]=low[v];
            }
            if(low[v]>dfn[u]){
                edge[i].flag=1;
                edge[i^1].flag=1;
            }
        }else if(low[u]>dfn[v]){
            low[u]=dfn[v];
        }
    }
}

int main(){
    int n,m;
    int Case=1;
    while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
        init();
        while(m--){
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]){
                tarjan(i,i);
            }
        }
        printf("%d\n\n",Case++);
        for(int i=0;i<tot;i++){
            if(edge[i].flag==1){
                printf("%d %d\n",edge[i^1].to,edge[i].to);
            }
        }
        printf("#\n");
    }
}

猜你喜欢

转载自blog.csdn.net/qq_40679299/article/details/85016489