zoukankan      html  css  js  c++  java
  • Tarjin + 缩点

    链接:https://www.nowcoder.com/acm/contest/81/C
    来源:牛客网

    题目描述

    给出一个 0 ≤ N ≤ 105 点数、0 ≤ M ≤ 105 边数的有向图,
    输出一个尽可能小的点集,使得从这些点出发能够到达任意一点,如果有多个这样的集合,输出这些集合升序排序后字典序最小的。

    输入描述:

    第一行为两个整数 1 ≤ n, m ≤ 10
    5

    接下来 M 行,每行两个整数 1 ≤ u, v ≤ 10
    5
     表示从点 u 至点 v 有一条有向边。
    数据保证没有重边、自环。

    输出描述:

    第一行输出一个整数 z,表示作为答案的点集的大小;
    第二行输出 z 个整数,升序排序,表示作为答案的点集。
    示例1

    输入

    7 10
    4 5
    5 1
    2 5
    6 5
    7 2
    4 2
    1 2
    5 3
    3 5
    3 6

    输出

    2
    4 7

    题意 : 寻找最小的点集,使得从这些点出发的可以遍历整张图
    思路分析 : Trajin + 缩点
    代码示例 :
    const int maxn = 1e5+10;
    
    vector<int>ve[maxn];
    vector<int>id[maxn]; // 强连通的编号
    int n, m;
    int dfn[maxn], low[maxn]; // 每个点在这棵树中,最小的子树的根
    int tot = 0, key = 0;
    int Stack[maxn], belong[maxn]; // 缩点
    bool instack[maxn];
    int scc; // 强连通分量的个数
    
    void tarjin(int x){
        low[x] = dfn[x] = ++key; // 注意是 ++在前,因为下面下面深搜的判断是为0表示没访问过的点,才去搜
        Stack[tot++] = x;
        instack[x] = true;
    
        for(int i = 0; i < ve[x].size(); i++){
            int to = ve[x][i];
            
            if (!dfn[to]) {
                tarjin(to);
                low[x] = min(low[x], low[to]);
            }
            else if (instack[to]){
                low[x] = min(low[x], dfn[to]);
            }
        } 
        if (low[x] == dfn[x]){
            scc++;
            int v;
            do{
                v = Stack[--tot];
                instack[v] = false;
                belong[v] = scc;
                id[scc].push_back(v);
            }
            while(v != x); 
        }  
    }
    int u[maxn], v[maxn], in[maxn];
    vector<int>ans;
    
    void solve(){
        
    }
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        cin >> n >> m;
        int a, b;
        
        memset(dfn, 0, sizeof(dfn));
        memset(low, 0, sizeof(low));
        memset(instack, false, sizeof(instack));
        memset(in, 0, sizeof(in));
        for(int i = 1; i <= m; i++){
            scanf("%d%d", &u[i], &v[i]);
            ve[u[i]].push_back(v[i]);
        }
        for(int i = 1; i <= n; i++){
            if (!dfn[i]) tarjin(i);
        }
       
        //for(int i = 1; i <= n; i++) printf("%d ", belong[i]);    
        for(int i = 1; i <= m; i++){
            if (belong[u[i]] == belong[v[i]]) continue;
            in[belong[v[i]]]++;
        }
        for(int i = 1; i <= scc; i++) sort(id[i].begin(), id[i].end());
        for(int i = 1; i <= scc; i++){
            if (!in[i]) {
                ans.push_back(id[i][0]);
            }
        }
        sort(ans.begin(), ans.end());
        printf("%d
    ", ans.size());
        for(int i = 0; i < ans.size(); i++){
            printf("%d%c", ans[i], i==ans.size()-1?'
    ':' ');
        }
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    从零起步搭建Hadoop单机和伪分布式开发环境图文教程
    使用DOM技术操纵文档
    求数组的子数组之和的最大值
    设计时(DesignTime)和运行时(RunTime)的区别
    ubuntu上ssh客户端应用
    创建一个简单的基于MVC的Django项目
    终结点与服务寄宿
    Google文件系统(GFS)翻译学习
    模板引擎开发(二)值标签的处理
    移动App服务端架构设计
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8902382.html
Copyright © 2011-2022 走看看