poj——The Bottom of a Graph
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 11044   Accepted: 4542

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. ThenG=(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+1is 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是汇点须满足 --- 对图中任意点u,若v可以到达u则必有u到v的路径;若v不可以到达u,则u到v的路径可有可无。
题目大意:
如果v点能够到的点,反过来能够到达v点,则称这个点为sink点,输出所有的sink点
思路:
我们这样想:对于一对点如果他们能够相互到达,那么他们在缩点是一定能缩成一个点,这样我们剩下的就是不能缩点的情况了。
也就是说我们缩完点后就剩下两种情况:1.这个点连向其它的点但是那个点不连向他   2.这个点不连向任意点
在这两种情况中第二种情况对于sink点的要求是显然成立的。而第一种情况是不成立的,因为这种情况一定是另一个点不连向这个点的,也就是说她是单向的。
(最开始没明白的地方。。。)
我们为何要在判断一个点的出度为0时循环到n??
因为我们把这些点缩成一个点,这样我们在进行判断每一个点的时候有两种选择:
1.我们先将出度为零的强连通分量记录在一个数组中。然后再用一个双重循环来判断一下那个点在这个数组中
2.我们用一个一重循环,循环到n,判断这个点所属的强连通分量缩点后对应的点的出度是否为0,若是0,用一个数组将其储存下来。
排序
输出这个数组内的元素
代码:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 10000
using namespace std;
bool vis[N];
int n,m,x,y,sum,tim,tot,top;
int out[N],dfn[N],low[N],ans[N],head[N],stack[N],belong[N],point[N];
inline int read()
{
    ,f=;char ch=getchar();
    ;ch=getchar();}
    +ch-';ch=getchar();}
    return f*x;
}
struct Edge
{
    int from,to,next;
 }edge[500010];
void add(int x,int y)
{
    tot++;
    edge[tot].to=y;
    edge[tot].next=head[x];
    head[x]=tot;
}
void begin()
{
    tot=;top=;sum=,tim=;
    memset(edge,,sizeof(edge));
    memset(stack,,sizeof(stack));
    memset(head,,sizeof(head));
    memset(,sizeof(out));
    memset(dfn,,sizeof(dfn));
    memset(low,,sizeof(low));
    memset(belong,,sizeof(belong));
    memset(ans,,sizeof(ans));
}
int tarjan(int now)
{
    dfn[now]=low[now]=++tim;
    stack[++top]=now;vis[now]=true;
    for(int i=head[now];i;i=edge[i].next)
    {
        int t=edge[i].to;
        if(vis[t]) low[now]=min(low[now],dfn[t]);
        else if(!dfn[t]) tarjan(t),low[now]=min(low[now],low[t]);
    }
    if(dfn[now]==low[now])
    {
        sum++;belong[now]=sum;
        for(;stack[top]!=now;top--)
        {
            vis[stack[top]]=false;
            belong[stack[top]]=sum;
            }
        vis[now]=false;top--;
    }
 }
void shrink_point()
{
    ;i<=n;i++)
     for(int j=head[i];j;j=edge[j].next)
      if(belong[i]!=belong[edge[j].to])
        out[belong[i]]++;
}
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        m=read();begin();
        ;i<=m;i++)
            x=read(),y=read(),add(x,y);
        ;i<=n;i++)
          if(!dfn[i]) tarjan(i);
        shrink_point();
        x=;
        ;i<=n;i++)
          if(!out[belong[i]]) ans[++x]=i;
        sort(ans+,ans++x);
        if(x)
        {
            ;i<x;i++)
              printf("%d ",ans[i]);
            printf("%d\n",ans[x]);
        }
        else printf("\n");
    }
    ;
}

注意:注意数组的大小!!

The Bottom of a Graph的更多相关文章

  1. The Bottom of a Graph(tarjan + 缩点)

    The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 9139   Accepted:  ...

  2. poj 2553 The Bottom of a Graph(强连通分量+缩点)

    题目地址:http://poj.org/problem?id=2553 The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K ...

  3. poj 2553 The Bottom of a Graph【强连通分量求汇点个数】

    The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 9641   Accepted:  ...

  4. POJ 2553 The Bottom of a Graph (Tarjan)

    The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 11981   Accepted: ...

  5. 【图论】The Bottom of a Graph

    [POJ2553]The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 11182   ...

  6. POJ 2553 The Bottom of a Graph(强连通分量)

    POJ 2553 The Bottom of a Graph 题目链接 题意:给定一个有向图,求出度为0的强连通分量 思路:缩点搞就可以 代码: #include <cstdio> #in ...

  7. poj--2553--The Bottom of a Graph (scc+缩点)

    The Bottom of a Graph Time Limit : 6000/3000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Oth ...

  8. POJ——T2553 The Bottom of a Graph

    http://poj.org/problem?id=2553 Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 10987   ...

  9. POJ-2552-The Bottom of a Graph 强连通分量

    链接: https://vjudge.net/problem/POJ-2553 题意: We will use the following (standard) definitions from gr ...

随机推荐

  1. 一条update语句优化小记

    遇到性能问题的sql如下: sql1: UPDATE amlclientlevel a SET    a.client_value = (SELECT l.client_value           ...

  2. c++:delete或free报错,语法正常。

    #include <stdio.h> #include <iostream> int _tmain(int argc, _TCHAR* argv[]) { ]; memcpy( ...

  3. QT +坐标系统 + 自定义控件 + 对象树的验证(自动进行析构)_内存回收机制

    通过创建一个新的按钮类,来进行析构函数的验证,即对象树概念的验证.当程序结束的时候会自动的调用析构函数, 验证思路: 要验证按钮会不会自动的析构,(即在QPushButton类里面的析构函数添加qDe ...

  4. C++构造函数(复制构造函数)、析构函数

    注:若类中没有显示的写如下函数,编译会自动生成:默认复制构造函数.默认赋值构造函数(浅拷贝).默认=运算符重载函数(浅拷贝).析构函数: 1.默认构造函数(默认值)构造函数的作用:初始化对象的数据成员 ...

  5. No-5.远程管理常用命令

    远程管理常用命令 目标 关机/重启 shutdown 查看或配置网卡信息 ifconfig ping 远程登录和复制文件 ssh scp 01. 关机/重启 序号 命令 对应英文 作用 01 shut ...

  6. Tunnelier使用说明

    Tunnelier与MyEnTunnel类似,但是功能更加强大.MyEnTunnel小巧易用,如何使用MyEnTunnel可以参考 MyEnTunnel使用说明 这里列下Tunnelier的优点: 1 ...

  7. js hover 下拉框

    <div class="box"> <div class="a f">111111</div> <div class= ...

  8. 前端 (cookie )页面进入存储一次

     <!--引入jq--> <script> var isShowTip = window.sessionStorage.getItem("isShow") ...

  9. Sphinx排序模式

    目前SPHINX支持6种排序模式.分别是: 1. SPH_SORT_RELEVANCE2. SPH_SORT_ATTR_DESC3. SPH_SORT_ATTR_ASC4. SPH_SORT_TIME ...

  10. UVa-133-救济金发放

    这题的话,我们首先对于移动函数可以知道,因为只是顺逆的关系,也就是加一或者减一,所以我们每次移动的时候,都补上一个小于n的最大整数,然后取模,这样就不会有负数,而且加之后的结果不会超过2*n,所以我们 ...