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

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 Gand 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

定义:点v是汇点须满足 --- 对图中任意点u,若v可以到达u则必有u到v的路径;若v不可以到达u,则u到v的路径可有可无。
题意:在n个点m条边的有向图里面,问有多少个点是汇点。
分析:首先若SCC里面有一个点不是汇点,那么它们全不是汇点,反之也如此。这也就意味着一个SCC里面的点要么全是,要么全不是。在求出SCC并缩点后,任一个编号为A的SCC若存在指向编号为B的SCC的边,那么它里面所有点必不是汇点(因为编号为B的SCC不可能存在指向编号为A的SCC的边)。若编号为A的SCC没有到达其他SCC的路径,那么该SCC里面所有点必是汇点。因此判断的关键在于SCC的出度是否为0.
思路:先用tarjan求出所有SCC,然后缩点后找出所有出度为0的SCC,并用数字存储点,升序排列后输出。
#include<stdio.h>
#include<string.h>
#include<vector>
#include<stack>
#include<algorithm>
#define MAX 21000
#define INF 0x3f3f3f
using namespace std;
int cost[MAX];
int low[MAX],dfn[MAX];
int head[MAX],instack[MAX];
int ans,n,m;
int sccno[MAX],clock;//sccno用来记录当前点属于哪个scc,
int scccnt;//记录总共有多少个scc
stack<int>s;
vector<int>newmap[MAX];//scc缩点之后储存新图
vector<int>scc[MAX];//用来记录scc中的点
int out[MAX];//记录scc的入度
int ant[MAX];
struct node
{
int beg,end,next;
}edge[MAX];
void init()
{
memset(head,-1,sizeof(head));
ans=0;
}
void add(int u,int v)
{
edge[ans].beg=u;
edge[ans].end=v;
edge[ans].next=head[u];
head[u]=ans++;
}
void getmap()
{
int i,j,a,b;
for(i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
}
}
void tarjan(int u)
{
int v,i,j;
low[u]=dfn[u]=++clock;
s.push(u);
instack[u]=1;
for(i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].end;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instack[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
scccnt++;
scc[scccnt].clear();//??
while(1)
{
v=s.top();
s.pop();
instack[v]=0;
sccno[v]=scccnt;
scc[scccnt].push_back(v);
if(v==u)
break;
}
}
}
void find(int l,int r)
{
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(sccno,0,sizeof(sccno));
memset(instack,0,sizeof(instack));
clock=scccnt=0;
for(int i=l;i<=r;i++)
{
if(!dfn[i])
tarjan(i);
}
}
void suodian()
{
int i,j;
for(i=1;i<=scccnt;i++)
{
newmap[i].clear();
out[i]=0;
}
for(i=0;i<ans;i++)//遍历所有的边
{
int u=sccno[edge[i].beg];//当前边的起点
int v=sccno[edge[i].end];//当前边的终点
if(u!=v)//因为sccno中记录的是当前点属于哪个scc,所以u!=v证明不在同一个scc但是由一条边相连,
{ //证明这两个scc联通
newmap[u].push_back(v);//将scc中的点储存下来 ??
out[u]++;//两个scc联通 则入度加一,
}
}
}
void solve()
{
int i,j,k=0;
for(i=1;i<=scccnt;i++)
{
if(out[i]==0)
{
for(j=0;j<scc[i].size();j++)
ant[k++]=scc[i][j];
}
}
sort(ant,ant+k);
for(i=0;i<k;i++)
{
if(i<k-1)
printf("%d ",ant[i]);
else
printf("%d",ant[i]);
}
printf("\n");
}
int main()
{
int j,i;
while(scanf("%d",&n),n)
{
scanf("%d",&m); init();
getmap();
find(1,n);
suodian();
solve();
}
return 0;
}

  

poj 2553 The Bottom of a Graph【强连通分量求汇点个数】的更多相关文章

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

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

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

    题目地址:POJ 2553 题目意思不好理解.题意是:G图中从v可达的全部点w,也都能够达到v,这种v称为sink.然后升序输出全部的sink. 对于一个强连通分量来说,全部的点都符合这一条件,可是假 ...

  3. poj - 2186 Popular Cows && poj - 2553 The Bottom of a Graph (强连通)

    http://poj.org/problem?id=2186 给定n头牛,m个关系,每个关系a,b表示a认为b是受欢迎的,但是不代表b认为a是受欢迎的,关系之间还有传递性,假如a->b,b-&g ...

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

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

  5. [poj 2553]The Bottom of a Graph[Tarjan强连通分量]

    题意: 求出度为0的强连通分量. 思路: 缩点 具体有两种实现: 1.遍历所有边, 边的两端点不在同一强连通分量的话, 将出发点所在强连通分量出度+1. #include <cstdio> ...

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

    题意: 求出图中所有汇点 定义:点v是汇点须满足 --- 对图中任意点u,若v可以到达u则必有u到v的路径:若v不可以到达u,则u到v的路径可有可无. 模板:http://www.cnblogs.co ...

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

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

  8. POJ 2553 The Bottom of a Graph Tarjan找环缩点(题解解释输入)

    Description We will use the following (standard) definitions from graph theory. Let V be a nonempty ...

  9. poj 2553 The Bottom of a Graph

    求解的是有向图中满足“自己可达的顶点都能到达自己”的顶点个数如果强连通分量中某个顶点,还能到达分量外的顶点,则该连通分量不满足要求// 因此,本题要求的是将强连通分量缩点后所构造的新图中出度为0的顶点 ...

随机推荐

  1. 水晶报表显示到aspx页面中

    1.在前台添加水晶报表显示控件. <CR:CrystalReportViewer ID="CrystalReportViewer1" runat="server&q ...

  2. ubuntu 下安装 apache php mysql

    ubuntu 安装 apache+php+mysql1.打开终端,输入“sudo apt-get install apache2”,回车;(安装apache2.0或2.x新版本,系统会自动查找新的版本 ...

  3. TDirectory.Copy复制文件

    描述:复制文件夹以及文件夹下的内容 procedure Copy(const SourceDirName, DestDirName: string) 参数一:源文件夹 参数二:目标文件夹 所在单元:S ...

  4. QQ宠物吹泡泡游戏小助手 VC++6.0代码分析

    最近玩QQ宠物,他总是心情低落,让我很不爽,让他玩耍吧,还得自己点鼠标,所以想偷个懒,试试能不能编个程序让电脑帮我做这个事情. 要干这件事就得先找一个游戏开刀,刚开始我找的是弹力球游戏,不就是点鼠标么 ...

  5. Windows命令行语法说明

    摘自:http://lavasoft.blog.51cto.com/62575/1113234   Windows命令行语法说明   说来惭愧,用windows这么多年了,对其命令行语法看得似懂非懂, ...

  6. 玩转createjs

    标题党"玩转", 真的是在玩怎么转... 参考一篇很经典的博文:createjs入门 做移动版(750x1334)的时候出来不居中啊, 不是掉在下面就是滑到右面, canvas里面 ...

  7. win7 安装SQL Server 2005 开发版 图文教程

    转自win7 安装SQL Server 2005 开发版 图文教程 ----------------------------写在安装前------------------------------ 一. ...

  8. Google面试题之100层仍两个棋子

    一道Google面试题,题目如下:"有一个100层高的大厦,你手中有两个相同的玻璃围棋子.从这个大厦的某一层扔下围棋子就会碎,用你手中的这两个玻璃围棋子,找出一个最优的策略,来得知那个临界层 ...

  9. 使用 Cloud Insight SDK 监控北京空气质量!

    现在越来越多的 App 都开始有广告了.特别是空气质量监测,和天气类的 App,广告还是蛮多的,眼花缭乱,真是够了. 最近刚好在用一款系统监控工具 Cloud Insight,它提供的 SDK 可以把 ...

  10. SPRING IN ACTION 第4版笔记-第一章-004-用类来管理DI

    一. 1. package chapter01.sia.knights.config; import org.springframework.context.annotation.Bean; impo ...