• poj2533 The Bottom of a Graph(Tarjan+缩点)


    Time Limit: 3000MS   Memory Limit: 65536K
    Total Submissions: 12659   Accepted: 5211

    Description

    We will use the following (standard) definitions from graph theory. Let V be a nonempty and finite set, its elements being called vertices (or nodes). Let E be a subset of the Cartesian product V×V, its elements being called edges. Then G=(V,E) is called a directed graph. 
    Let n be a positive integer, and let p=(e1,...,en) be a sequence of length n of edges ei∈E such that ei=(vi,vi+1) for a sequence of vertices (v1,...,vn+1). Then p is called a path from vertex v1 to vertex vn+1 in G and we say that vn+1 is reachable from v1, writing (v1→vn+1)
    Here are some new definitions. A node v in a graph G=(V,E) is called a sink, if for every node w in G that is reachable from vv is also reachable from w. The bottom of a graph is the subset of all nodes that are sinks, i.e., bottom(G)={v∈V|∀w∈V:(v→w)⇒(w→v)}. You have to calculate the bottom of certain graphs.

    Input

    The input contains several test cases, each of which corresponds to a directed graph G. Each test case starts with an integer number v, denoting the number of vertices of G=(V,E), where the vertices will be identified by the integer numbers in the set V={1,...,v}. You may assume that 1<=v<=5000. That is followed by a non-negative integer e and, thereafter, e pairs of vertex identifiers v1,w1,...,ve,we with the meaning that (vi,wi)∈E. There are no edges other than specified by these pairs. The last test case is followed by a zero.

    Output

    For each test case output the bottom of the specified graph on a single line. To this end, print the numbers of all nodes that are sinks in sorted order separated by a single space character. If the bottom is empty, print an empty line.

    Sample Input

    3 3
    1 3 2 3 3 1
    2 1
    1 2
    0
    

    Sample Output

    1 3
    2
    

    Source

     
    题目大意
    多组数据输入,v个点,e条边,接下来一行是e对有向边,v为0时输入结束
    求解最底端的强连通分量,顺序输出
     
    思路
    用Tarjan算法先缩点,再判断哪些强连通分量的出度为0,升序输出这些强连通分量里面的点的编号
     
     1 #include <cstdio>
     2 #include <vector>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int N=5e3+5;
     8 int low[N],dfn[N],Stack[N],belong[N],cdu[N];
     9 bool inStack[N];
    10 int n,m,tot,tag,top;
    11 vector<int> g[N];
    12 vector<int> res;
    13 
    14 void init(){
    15     top=tag=0;
    16     memset(low,0,sizeof low);
    17     memset(dfn,0,sizeof dfn);
    18     memset(Stack,0,sizeof Stack);
    19     memset(belong,0,sizeof belong);
    20     memset(cdu,0,sizeof cdu);
    21     memset(inStack,false,sizeof inStack);
    22     res.clear();
    23     for(int i=0;i<N;i++){
    24         g[i].clear();
    25     }
    26 }
    27 
    28 void tarjan(int u){
    29     int v;
    30     low[u]=dfn[u]=++tot;
    31     Stack[++top]=u;
    32     inStack[u]=true;
    33     for(int i=0;i<g[u].size();i++){
    34         v=g[u][i];
    35         if(dfn[v]==0){
    36             tarjan(v);
    37             low[u]=min(low[u],low[v]);
    38         }
    39         else if(inStack[v]==true){
    40             low[u]=min(low[u],dfn[v]);
    41         }
    42     }
    43     if(dfn[u]==low[u]){
    44         tag++;
    45         do{
    46             v=Stack[top--];
    47             inStack[v]=false;
    48             belong[v]=tag;
    49         }while(u!=v);
    50     }
    51 }
    52 
    53 int main(){
    54     while(scanf("%d",&n),n){
    55         init();
    56         scanf("%d",&m);
    57         for(int i=1;i<=m;i++){
    58             int x,y;
    59             scanf("%d%d",&x,&y);
    60             g[x].push_back(y);
    61         }
    62         for(int i=1;i<=n;i++){
    63             if(dfn[i]==0){
    64                 tot=0;
    65                 tarjan(i);
    66             }
    67         }
    68         for(int i=1;i<=n;i++){
    69             for(int j=0;j<g[i].size();j++){
    70                 int x=g[i][j];
    71                 if(belong[i]!=belong[x]){
    72                     cdu[belong[i]]++;
    73                 }
    74             }
    75         }
    76 //        for(int i=1;i<=tag;i++){
    77 //            printf("%d",i);
    78 //            for(int j=0;j<vec[i].size();j++){
    79 //                printf(" %d",vec[i][j]);
    80 //            }
    81 //            printf("
    ");
    82 //        }
    83         for(int i=1;i<=tag;i++){
    84             if(cdu[i]>0) continue;
    85             for(int j=1;j<=n;j++){
    86                 if(belong[j]==i){
    87                     res.push_back(j);
    88                 }
    89             }
    90         }
    91         sort(res.begin(),res.end());
    92         for(int i=0;i<res.size();i++){
    93             if(i) printf(" ");
    94             printf("%d",res[i]);
    95         }
    96         printf("
    ");
    97     }
    98 }
  • 相关阅读:
    私有字段private也可以外部访问
    PHP连接MySQL数据库的三种方式(mysql、mysqli、pdo)
    数据库删除重复数据
    常见主流数据库对比介绍
    php方法重载
    php 析构函数,构造函数
    php中常量 const属性,静态属性,静态的函数方法
    面向对象(1)
    HDU 5047 Sawtooth 高精度
    HDU 5239 Doom 线段树
  • 原文地址:https://www.cnblogs.com/ChangeG1824/p/11424600.html
Copyright © 2020-2023  润新知