poj2553 强连通缩点

The Bottom of a Graph

Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 10114   Accepted: 4184

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

题意:

n个点,m条边,并且是单向边。求有多少个顶点,满足它能到的点也能够到达它。

思路:

对于强连通中的点,肯定能够互相到达,所以可以强连通缩点,此时只要找到出度为0的点,其连通分量连所有的点就是答案。因为

如果该点的出度不为0,那么肯定有新的该点能够到达的点,由于已经缩点了,不可能出现有强连通的情况,所以出度不为0的点不满足要求。

/*
 * Author:  sweat123
 * Created Time:  2016/6/25 14:32:24
 * File Name: main.cpp
 */
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<string>
#include<vector>
#include<cstdio>
#include<time.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1<<30
#define MOD 1000000007
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pi acos(-1.0)
using namespace std;
const int MAXN = 5010;
struct node{
    int from;
    int to;
    int next;
}edge[MAXN*10];
int pre[MAXN],vis[MAXN],dfn[MAXN],low[MAXN],n,m,ind;
int f[MAXN],siz[MAXN],num,dep,out[MAXN],in[MAXN];
stack<int>s;
vector<int>p[MAXN];
void add(int x,int y){
    edge[ind].from = x;
    edge[ind].to = y;
    edge[ind].next = pre[x];
    pre[x] = ind ++;
}
void dfs(int rt){
    dfn[rt] = low[rt] = ++dep;
    vis[rt] = 1;
    s.push(rt);
    for(int i = pre[rt]; i != -1; i = edge[i].next){
        int t = edge[i].to;
        if(!dfn[t]){
            dfs(t);
            low[rt] = min(low[rt],low[t]);
        } else if(vis[t]){
            low[rt] = min(low[rt],dfn[t]);
        }
    }
    if(low[rt] == dfn[rt]){
        ++num;
        while(!s.empty()){
            int  tp = s.top();
            s.pop();
            vis[tp] = 0;
            f[tp] = num;
            siz[num] ++;
            p[num].push_back(tp);
            if(tp == rt)break;
        }
    }
}
void setcc(){
    num = 0;
    dep = 0;
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    for(int i = 1; i <= n; i++){
        if(!dfn[i]){
            dfs(i);
        }
    }
    memset(pre,-1,sizeof(pre));
    int ret = ind;
    for(int i = 0; i < ret; i++){
        int x = f[edge[i].from];
        int y = f[edge[i].to];
        if(x == y)continue;
        add(x,y);
        out[x] ++;
        in[y] ++;
    }
    vector<int>ans;
    for(int i = 1; i <= num; i++){
        if(!out[i]){
            for(int j = 0; j < p[i].size(); j++){
                ans.push_back(p[i][j]);
            }
        }
    }
    sort(ans.begin(),ans.end());
    for(int i = 0; i < ans.size(); i++){
        if(i == 0)printf("%d",ans[i]);
        else printf(" %d",ans[i]);
    }
    printf("\n");
}
int main(){
    while(~scanf("%d",&n)){
        if(n == 0)break;
        scanf("%d",&m);
        if(n == 1){
            printf("1\n");
            continue;
        }
        ind = 0;
        for(int i = 1; i <= n; i++){
            p[i].clear();
        }
        memset(pre,-1,sizeof(pre));
        while(!s.empty())s.pop();
        memset(f,-1,sizeof(f));
        memset(siz,0,sizeof(siz));
        for(int i = 1; i <= m; i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        setcc();
    }
    return 0;
}

The Bottom of a Graph

Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 10114   Accepted: 4184

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
时间: 2024-10-03 14:56:59

poj2553 强连通缩点的相关文章

Light OJ 1168 Wishing Snake 强连通缩点+哈密顿通路

题目来源:Light OJ 1168 Wishing Snake 题意:有点难看懂题意 看了一个小时再加别人的代码才懂意思 从0开始 输入的那些每一对u v 都要经过 就是从0到到达那些点 思路:首先缩点 每一个强连通分量里面的点都是可达的 缩点后的图是有向无环图 如果从0这个强连通分量可以出去到2个强连通分量 那么这两个强连通分量是不可能相互可达 所以可行的方案就是所有的强连通分量连成一线 一个一个串起来 除了第一个 出度是1入度是0和最后一个出度是0入度是1 其他都是入度等于出度是1 特判只

强连通缩点— HDU1827

强连通缩点以后最终形成的是一棵树 我们可以根据树的性质来看缩点以后的强连通分量图,就很好理解了 /* gyt Live up to every day */ #include<cstdio> #include<cmath> #include<iostream> #include<algorithm> #include<vector> #include<stack> #include<cstring> #include<

BZOJ 1051: [HAOI2006]受欢迎的牛 强连通缩点

题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1051 题解: 强连通缩点得到DAG图,将图转置一下,对入度为零的点跑dfs看看能不能访问到所有的点. 代码: #include<iostream> #include<cstdio> #include<vector> #include<stack> #include<algorithm> #include<cstring> u

POJ3352Road Construction(边的双连通+强连通缩点)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8673   Accepted: 4330 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the ro

hdu3861The King’s Problem (强连通 缩点+最小路径覆盖)

The King's Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1606 Accepted Submission(s): 584 Problem Description In the Kingdom of Silence, the king has a new problem. There are N cities in

UVA - 11324 The Largest Clique 强连通缩点+记忆化dp

题目要求一个最大的弱联通图. 首先对于原图进行强连通缩点,得到新图,这个新图呈链状,类似树结构. 对新图进行记忆化dp,求一条权值最长的链,每个点的权值就是当前强连通分量点的个数. /* Tarjan算法求有向图的强连通分量set记录了强连通分量 Col记录了强连通分量的个数. */ #include <iostream> #include<cstring> #include<cstdio> #include<string> #include<algo

HDU 4971 A simple brute force problem. 强连通缩点+最大权闭合图

题意: 给定n个项目,m个技术难题 下面一行n个数字表示每个项目的收益 下面一行m个数字表示攻克每个技术难题的花费 下面n行第i行表示 第一个数字u表示完成 i 项目需要解决几个技术难题,后面u个数字表示需要解决的问题标号. 下面m*m的矩阵 (i,j) = 1 表示要解决j问题必须先解决i问题. (若几个问题成环,则需要一起解决) 问:最大收益. 思路: 先给问题缩点一下,每个缩点后的点权就是这个点内所有点权和. 然后跑一个最大权闭合图. #include<stdio.h> #include

hdu 4635(强连通+缩点)

http://acm.hdu.edu.cn/showproblem.php?pid=4635 Strongly connected Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1381    Accepted Submission(s): 587 Problem Description Give a simple directed

poj2186 强连通缩点

Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 29141   Accepted: 11779 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M &