zoukankan      html  css  js  c++  java
  • uva 610 强连通分量 / 桥

      Street Directions 

    According to the Automobile Collision Monitor (ACM), most fatal traffic accidents occur on two-way streets. In order to reduce the number of fatalities caused by traffic accidents, the mayor wants to convert as many streets as possible into one-way streets. You have been hired to perform this conversion, so that from each intersection, it is possible for a motorist to drive to all the other intersections following some route.


    You will be given a list of streets (all two-way) of the city. Each street connects two intersections, and does not go through an intersection. At most four streets meet at each intersection, and there is at most one street connecting any pair of intersections. It is possible for an intersection to be the end point of only one street. You may assume that it is possible for a motorist to drive from each destination to any other destination when every street is a two-way street.

    Input 

    The input consists of a number of cases. The first line of each case contains two integers n and m. The number of intersections is n ( $2 leŸ n leŸ 1000$), and the number of streets is m. The next m lines contain the intersections incident to each of the m streets. The intersections are numbered from 1 to n, and each street is listed once. If the pair $i j$ is present, $j i$ will not be present. End of input is indicated by n = m = 0.

    Output 

    For each case, print the case number (starting from 1) followed by a blank line. Next, print on separate lines each street as the pair $i j$ to indicate that the street has been assigned the direction going from intersection i to intersection j. For a street that cannot be converted into a one-way street, print both $i j$ and $j i$ on two different lines. The list of streets can be printed in any order. Terminate each case with a line containing a single `#' character.


    Note: There may be many possible direction assignments satisfying the requirements. Any such assignment is acceptable.

    Sample Input 

    7 10
    1 2
    1 3
    2 4
    3 4
    4 5
    4 6
    5 7
    6 7
    2 5
    3 6
    7 9
    1 2
    1 3
    1 4
    2 4
    3 4
    4 5
    5 6
    5 7
    7 6
    0 0
    

    Sample Output 

    1
    
    1 2
    2 4
    3 1
    3 6
    4 3
    5 2
    5 4
    6 4
    6 7
    7 5
    #
    2
    
    1 2
    2 4
    3 1
    4 1
    4 3
    4 5
    5 4
    5 6
    6 7
    7 5
    #
    


    Miguel A. Revilla
    1999-03-24
    tarjan遍历一遍,标记那些边是回边,需要走的非回边,桥,即可:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<stack>
    
    using namespace std;
    
    #define LL long long
    #define UINT unsigned int
    #define MAX_INT 0x7fffffff
    #define cint const int
    
    #define MAXN 1111
    #define MAXM 1111111
    
    struct edge{
        int u, v, nxt;
    }e[MAXM];
    int h[MAXN], cc, n, m;
    
    void add(int u, int v){
        e[cc]=(edge){u, v, h[u]};
        h[u]=cc++;
        e[cc]=(edge){v, u, h[v]};
        h[v]=cc++;
    }
    int dfn[MAXN], low[MAXN], vis[MAXM];
    int tsp;
    
    void tarjan(int u){
        dfn[u] = low[u] = ++tsp;
        for(int i=h[u]; i!=-1; i=e[i].nxt){
            int v = e[i].v;
            if(vis[i] || u==v){
                if(u==v) vis[i]=1, vis[i^1]=-1;
                continue;
            }
            vis[i]=1, vis[i^1]=-1;          //走的边,反向边
            if(!dfn[v]) tarjan(v);
            low[u] = min(low[u], low[v]);
            if(dfn[u]<low[v]) vis[i^1]=1;   //桥
        }
    }
    
    void solve(){
        fill_n(vis, cc, 0);
        fill_n(dfn+1, n, 0);
        tsp=0;  tarjan(1);
        for(int i=0; i<cc; i++) if(vis[i]==1){
            int u = e[i].u, v = e[i].v;
            printf("%d %d
    ", u, v);
        }
    }
    
    int main(){
    //    freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin);
        int kase=1;
        while(scanf(" %d %d", &n, &m)==2 && n){
            int i, u, v;
            fill_n(h+1, n, -1);     cc=0;
            while(m--){
                scanf(" %d %d", &u, &v);
                add(u, v);
            }
            printf("%d
    
    ", kase++);
            solve();
            printf("#
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    Android 网络优化,使用 HTTPDNS 优化 DNS,从原理到 OkHttp 集成
    WebView,我已经长大了,知道自己区分是否安全了!
    “崩溃了?不可能,我全 Catch 住了” | Java 异常处理
    Google 的 QUIC 华丽转身成为下一代网络协议: HTTP/3.0
    图解:HTTP 范围请求,助力断点续传、多线程下载的核心原理
    c/c++ 读入一行不确定个数的整数
    LeetCode:Length of Last Word
    LeetCode:Permutation Sequence
    机器学习:判别模型与生成模型
    LeetCode:Jump Game I II
  • 原文地址:https://www.cnblogs.com/ramanujan/p/3379810.html
Copyright © 2011-2022 走看看