• 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
    ",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
    ",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
    ",e[i].to,e[i^1].to);
            }
        }
    }
  • 相关阅读:
    C#发送邮件
    C# MD5加密
    html实现艺术字
    sql日期转换比较问题
    web 抓取
    NHibernate主要数据操作方法
    写日志
    备忘 sql分页
    自我介绍
    企业级应用和互联网应用的区别
  • 原文地址:https://www.cnblogs.com/00isok/p/10759937.html
Copyright © 2020-2023  润新知