首页 > 其他 > 详细

POJ2553( 有向图缩点)

时间:2016-01-29 21:01:07      阅读:225      评论:0      收藏:0      [点我收藏+]
The Bottom of a Graph
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 9779   Accepted: 4063

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
题意:给定一幅有向图,若某点所能到达的点也能到达其本身,那么这个点为sink。由小到大输出sink.
思路:有向图缩点得到一棵树,答案为构成叶子(出度为0)结点的连通分量。
#include"cstdio"
#include"cstring"
#include"algorithm"
#include"vector"
using namespace std;
const int MAXN=5005;
struct Edge{
    int to,next;
}es[MAXN*MAXN];
int V,E;
int head[MAXN],ant;
void add_edge(int u,int v)
{
    es[ant].to=v;
    es[ant].next=head[u];
    head[u]=ant++;
}
int index;
int dfn[MAXN],low[MAXN];
int stack[MAXN],top;
int cpnt[MAXN],cnt;
void tarjan(int u)
{
    stack[top++]=u;
    dfn[u]=low[u]=++index;
    for(int i=head[u];i!=-1;i=es[i].next)
    {
        int to=es[i].to;
        if(!dfn[to])
        {
            tarjan(to);
            low[u]=min(low[u],low[to]);
        }
        else low[u]=min(low[u],dfn[to]);
    }
    if(dfn[u]==low[u])
    {
        int v;
        cnt++;
        do{
            v=stack[--top];
            cpnt[v]=cnt;
        }while(u!=v);
    }
}
int deg[MAXN];
int res[MAXN];
int s;
void seek()
{
    for(int i=1;i<=V;i++)
    {
        for(int j=head[i];j!=-1;j=es[j].next)
        {
            int to=es[j].to;
            if(cpnt[i]!=cpnt[to])
            {
                deg[cpnt[i]]++;
            }
        }
    }
    for(int i=1;i<=V;i++)
    {
        if(deg[cpnt[i]]==0)
        {
            res[s++]=i;
        }
    }
}
int main()
{
    while(scanf("%d",&V)!=EOF&&V)
    {
        scanf("%d",&E);
        s=0;
        memset(head,-1,sizeof(head));
        ant=0;
        index=0;
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        top=0;
        memset(cpnt,0,sizeof(cpnt));
        cnt=0;
        memset(deg,0,sizeof(deg));
        for(int i=0;i<E;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add_edge(u,v);
        }
        for(int i=1;i<=V;i++)
            if(!dfn[i])
                tarjan(i);//注意无向图与有向图的缩点方式 
        seek();
        if(s==0)
        {
            printf("\n");
        }
        else
        {
            for(int i=0;i<s-1;i++)
            {
                printf("%d ",res[i]);
            }
            printf("%d\n",res[s-1]);
        }
    }
    return 0;
}

下面是kosaraju算法

#include"cstdio"
#include"cstring"
#include"vector"
using namespace std;
const int MAXN=5005;
vector<int> G[MAXN];
vector<int> rG[MAXN];
vector<int> vs;
int V,E;

int cpnt[MAXN];
int vis[MAXN];
void dfs(int u)
{
    vis[u]=1;
    for(int i=0;i<G[u].size();i++)
        if(!vis[G[u][i]])    dfs(G[u][i]);
    vs.push_back(u);
}

void rdfs(int u,int k)
{
    cpnt[u]=k;
    vis[u]=1;
    for(int i=0;i<rG[u].size();i++)
        if(!vis[rG[u][i]])    rdfs(rG[u][i],k);
}

void scc()
{
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=V;i++)
        if(!vis[i])    dfs(i);
    memset(vis,0,sizeof(vis));
    int k=1;
    for(int i=vs.size()-1;i>=0;i--)
        if(!vis[vs[i]])    rdfs(vs[i],k++);
}

int deg[MAXN];
void solve()
{
    scc();
    for(int i=1;i<=V;i++)
    {
        for(int j=0;j<G[i].size();j++)
        {
            int to=G[i][j];
            if(cpnt[i]!=cpnt[to])
            {
                deg[cpnt[i]]++;
            }
        }
    }
    int flag=0;
    for(int i=1;i<=V;i++)
    {
        if(deg[cpnt[i]]==0)
        {
            if(flag==0)
            {
                printf("%d",i);
                flag=1;
            }
            else
            {
                printf(" %d",i);
            }
        }
    }
    printf("\n");
}
int main()
{
    while(scanf("%d",&V)!=EOF&&V)
    {
        scanf("%d",&E);
        vs.clear();
        memset(cpnt,0,sizeof(cpnt));
        memset(deg,0,sizeof(deg));
        for(int i=1;i<=V;i++)
        {
            G[i].clear();
            rG[i].clear();
        }
        for(int i=0;i<E;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            rG[v].push_back(u);    
        }
        solve();
    }
        
    return 0;
}

 

POJ2553( 有向图缩点)

原文:http://www.cnblogs.com/program-ccc/p/5169604.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!