POJ--2553The Bottom of a Graph--强连通分量+缩点

The Bottom of a Graph

Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 12596 Accepted: 5177

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

Ulm Local 2003

 

要求的是缩点点集,要求缩点的点,如果u->v,那么v->u。需要注意:假如u是缩点X内的点,而v不是,如果u->v,而v不能到达u,就不行。需要排序输出。


缩点之后,染色,对于每一条边u->,若他俩不属于一个强连通分量,那么u所属的强连通分量度数+1。最后判断,对于每一个强连通分量,判断若其度数为0,找出所有属于其的点,排序后输出即可。

#include <algorithm>    //STL通用算法
#include <bitset>     //STL位集容器
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>     //复数类
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>      //STL双端队列容器
#include <exception>    //异常处理类
#include <fstream>
#include <functional>   //STL定义运算函数(代替运算符)
#include <limits>
#include <list>      //STL线性列表容器
#include <map>       //STL 映射容器
#include <iomanip>
#include <ios>      //基本输入/输出支持
#include<iosfwd>     //输入/输出系统使用的前置声明
#include <iostream>
#include <istream>     //基本输入流
#include <ostream>     //基本输出流
#include <queue>      //STL队列容器
#include <set>       //STL 集合容器
#include <sstream>    //基于字符串的流
#include <stack>      //STL堆栈容器    
#include <stdexcept>    //标准异常类
#include <streambuf>   //底层输入/输出支持
#include <string>     //字符串类
#include <utility>     //STL通用模板类
#include <vector>     //STL动态数组容器
#include <cwchar>
#include <cwctype>
#define ll long long
using namespace std;
//priority_queue<int,vector<int>,less<int> >q;
int dx[]= {-1,1,0,0,-1,-1,1,1};
int dy[]= {0,0,-1,1,-1,1,1,-1};
const int maxn = 30005;;
const ll mod=10007;
const int MAXM = 150005;
struct Edge
{
    int from,to,next;
} e[MAXM];
int dfn[maxn],low[maxn],head[maxn],link[maxn],visx,tot,tot_edge;
int n,m,cnt,belong[maxn],in[maxn],dis[maxn],a[maxn],sum[maxn];
bool exist[maxn],vis[maxn];
int deg[maxn];
int ans[maxn];
void PrePare()
{
    cnt=0;
    visx=0;
    tot=0;
    memset(dfn,-1,sizeof dfn );
    memset(low,-1,sizeof low );
    memset(head,0,sizeof head );
    memset(link,0,sizeof link );
    memset(belong,0,sizeof belong );
    memset(exist,0,sizeof exist );
    memset(sum,0,sizeof sum );
    memset(in,0,sizeof in );
    memset(deg,0,sizeof(deg));
    //for(int i=1; i<=n; i++)
        //scanf("%d",&a[i]),a[i]=max(a[i],0);
}
void Add_Edge(int u,int v,int *head)
{
    e[++tot].to=v;
    e[tot].from=u;
    e[tot].next=head[u];
    head[u]=tot;
}
stack<int> st;
void Tarjan(int u)
{
    dfn[u]=low[u]= ++visx;
    st.push(u);
    exist[u]=true;
    for(int i=head[u]; i; i=e[i].next)
    {
        int v=e[i].to;
        if(dfn[v]==-1)
        {
            Tarjan(v);
            low[u]=min(low[v],low[u]);
        }
        else if(exist[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u])
    {
        ++cnt;//强连通点的个数
        while(1)
        {
            int v=st.top();
            st.pop();
            exist[v]=0;
            belong[v]=cnt;//v这个
            //in[cnt]++;
            //sum[cnt]+=a[v];//看这个缩点的权值,权值额外保存
            if(v==u)
                break;
        }
    }
}
void new_Map()
{
    for(int i=1; i<=n; i++)
        for(int j=head[i]; j; j=e[j].next)
        {
            int v=e[j].to;
            if(belong[i]!=belong[v])
            {
                deg[belong[i]]++;
            }
        }
}
void solve()
{
    int tot=0;
    for(int i=1;i<=cnt;i++)
    {
        if(deg[i]>0)continue;

        for(int j=1;j<=n;j++)
        {
            if(belong[j]==i)
            ans[tot++]=j;
        }
    }
    sort(ans,ans+tot);
    for(int i=0;i<tot;i++)
    {
        cout<<ans[i]<<" ";
    }
    cout<<endl;
}
queue<int> q;
int dij(int S)
{
    int rt=dis[S]=sum[S];
    memset(vis,0,sizeof vis );
    q.push(S);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        if(vis[u])
            continue;
        vis[u]=1;
        for(int i=link[u]; i; i=e[i].next)
        {
            int v=e[i].to;
            dis[v]=max(dis[v],dis[u]+sum[v]);
            rt=max(rt,dis[v]);
            q.push(v);//求最长路
        }
    }
    return rt;
}
int main()
{
    while(scanf("%d",&n))
    {
        if(!n)return 0;
        scanf("%d",&m);
        PrePare();
        for(int u,v,i=1; i<=m; i++)
        {
            scanf("%d%d",&u,&v);
            Add_Edge(u,v,head);
        }
        memset(dis,0,sizeof dis );
        for(int i=1; i<=n; i++)
            if(dfn[i]==-1)
                Tarjan(i);//缩点
        new_Map();
        solve();
    }
    return 0;
}

 

python023基于Python旅游景点推荐系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
JSP基于SSM网上医院预约挂号系统毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值