POJ 1438 One-way Traffic (混合图+边双连通)

<题目链接>

题目大意:

给定一个混合图,问你在能够使得图中所有点能够两两到达的情况下,尽可能多的将无向边变成有向边,输出这些无向边的变化方案。

解题分析:
这与之前做过的这道题非常类似 POJ 1515 ,不同的是,本题是混合图。总体的思路还是相同的,就是将无向边定向,但是原图中的桥一定只能是双向的,否则不可能使得所有点两两相互到达,之后就是记录一下无向边定向后的结果即可。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;

#define rep(i,s,t) for(int i=s;i<=t;i++)
#define clr(a,b) memset(a,b,sizeof a)
const int N = 2e3+5 , M = N*N;

struct Edge{ int to,nxt,fp,cur; }e[M];    //fp表示这是单向边,双向边,或者在原图中不存在,cur用来给这条边定向

int n,m,cnt,tot;
int head[N],low[N],dfn[N];

inline void init(){
    cnt=tot=0;
    clr(dfn,0);clr(head,-1);clr(low,0);
}

inline void add(int u,int v,int flag){
    e[cnt]=(Edge){v,head[u],flag,-1};head[u]=cnt++;
}

void Tarjan(int u,int pre){
    dfn[u]=low[u]=++tot;
    for(int i=head[u];~i;i=e[i].nxt){
        int v=e[i].to;
        if(v==pre)continue;
        if(e[i].cur!=-1)continue;       //如果该边之前已经定过向
        if(!e[i].fp)continue;           //如果改边在原图中不存在
        e[i].cur=1,e[i^1].cur=0;
        if(!dfn[v]){
            Tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u])e[i].cur=e[i^1].cur=1;
        }else low[u]=min(low[u],dfn[v]);
    }
}

int main(){
    while(cin>>n>>m){
        init();
        rep(i,1,m){
            int u,v,c;scanf("%d%d%d",&u,&v,&c);
            if(c==1)add(u,v,1),add(v,u,0);
            else add(u,v,2),add(v,u,2);
        }
        rep(i,1,n) if(!dfn[i]){        
            Tarjan(i,-1);
        }
        //只输出双向边的处理方案
        for(int i=0;i<cnt;i+=2){
            if(e[i].fp==2&&e[i].cur==1&&e[i^1].cur==1)printf("%d %d 2\n",e[i^1].to,e[i].to);
            else if(e[i].fp==2&&e[i].cur==1&&e[i^1].cur==0)printf("%d %d 1\n",e[i^1].to,e[i].to);     //e[i]边有效,所以是e[i^1].to--->e[i].to
            else if(e[i].fp==2&&e[i].cur==0&&e[i^1].cur==1)printf("%d %d 1\n",e[i].to,e[i^1].to);
        }
    }
}

 

posted @ 2019-04-23 23:52  悠悠呦~  阅读(186)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end