您的位置:首页 > 其它

poj 2553 zoj 1979 The Bottom of a Graph(强联通分量 Tarjan)

2015-03-28 00:37 603 查看
The Bottom of a Graph

Time Limit: 3000MSMemory Limit: 65536K
Total Submissions: 9176Accepted: 3808
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 v, v 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
Ulm Local 2003

定义了一个图的底部

找出所有的联通分量 在这个里面所有的点与点之间是互相可达的

先进行缩点 构造DAG 找出其中的叶子节点(出度为0的点)

因为出度为0 所以 这个点没有到其他点的路径 保证了这个连通分量中所有的点与点之间都是可达的

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <queue>

#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define INF 99999999
#define ll __int64
#define bug cout<<"here"<<endl
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)

using namespace std;

void read(int &x)
{
    char ch;
    x=0;
    while(ch=getchar(),ch!=' '&&ch!='\n')
    {
        x=x*10+ch-'0';
    }
}

const int MAXN=5010;
const int MAXM=50010;
struct Edge
{
    int to,next;
}edge[MAXM];
int head[MAXN],tot;
int low[MAXN],dfn[MAXN],sta[MAXN],belong[MAXN];
int Index,top;
int scc;
bool instack[MAXN];
int num[MAXN];
int n,m;

void addedge(int u,int v)
{
    edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++;
}

void Tarjan(int u)
{
//    bug;
    int v;
    low[u]=dfn[u]=++Index;
    sta[top++]=u;
    instack[u]=1;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
//        bug;
        v=edge[i].to;
        if(!dfn[v])
        {
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(instack[v])
            low[u]=min(low[u],dfn[v]);
    }
//    bug;
    if(low[u]==dfn[u])
    {
        scc++;
        do{
            v=sta[--top];
            instack[v]=0;
            belong[v]=scc;
            num[scc]++;
        }while(u!=v);
    }
}

int cd[MAXN];
void solve()
{
//    bug;
    MEM(dfn,0);
    MEM(instack,0);
    MEM(cd,0);
    MEM(num,0);
    Index=scc=top=0;
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            Tarjan(i);
    for(int u=1;u<=n;u++)
    {
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(belong[u]!=belong[v])
                cd[belong[u]]++;
        }
    }
    int cnt=0;
    int x;
    int flag=0;
    for(int i=1;i<=n;i++)
    {
        int u=belong[i];
        if(cd[u]==0)
        {
            if(flag) printf(" ");
            printf("%d",i);
            flag=1;
        }
    }
    puts("");
}
void init()
{
    tot=0;
    MEM(head,-1);
}

int main()
{
//    fread;
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0) break;
        scanf("%d",&m);
        init();
        for(int i=0;i<m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
        }
        solve();
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: