zoukankan      html  css  js  c++  java
  • 牛客网 Wannafly挑战赛14 C.可达性(tarjan缩点)

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

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 262144K,其他语言524288K
    64bit IO Format: %lld
    题目描述
    给出一个 0 ≤ N ≤ 105 点数、0 ≤ M ≤ 105 边数的有向图,
    输出一个尽可能小的点集,使得从这些点出发能够到达任意一点,如果有多个这样的集合,输出这些集合升序排序后字典序最小的。
    输入描述:

    第一行为两个整数 1 ≤ n, m ≤ 105,
    接下来 M 行,每行两个整数 1 ≤ u, v ≤ 105 表示从点 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

    分析:首先,所有的入度为0的点必然要放入到集合中,否则不会最优。排除掉这些点后,剩下的点组成的图中,没有入度为0的点,则必然有环,将环进行缩点,以环中最小的点的编号作为其编号,找到新的入度为0的点,放入集合中。

    代码如下:

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <iostream>
    #include <vector>
    #include <stack>
    using namespace std;
    const int MAXN=1e5+100;
    int dfn[MAXN],low[MAXN],vis[MAXN];
    int in[MAXN];
    int root[MAXN];
    vector<int>path[MAXN];
    vector<int>ans;
    stack<int>S;
    int n,m,u,v,tot;
    struct node
    {
        int u;
        int v;
    }edge[MAXN];
    void tarjan(int x)
    {
        low[x]=dfn[x]=++tot;
        S.push(x);vis[x]=1;
        for(int i=0;i<path[x].size();i++)
        {
           int v=path[x][i];
           if(!dfn[v])
           {
               tarjan(v);
               low[x]=min(low[x],low[v]);
           }
           else if(vis[v])
               low[x]=min(low[x],low[v]);
        }
    
        if(low[x]==dfn[x])
        {
           while(!S.empty())
           {
              int now=S.top();
              root[now]=x;
              vis[now]=0;
              S.pop();
              if(now==x)break;
           }
        }
    }
    
    int main()
    {
        tot=0;
        scanf("%d%d",&n,&m);
        for(int k=1;k<=m;k++)
        {
         scanf("%d%d",&u,&v);
         edge[k].u=u,edge[k].v=v;
         path[u].push_back(v);
        }
    
        for(int i=1;i<=n;i++)
        {
          if(!dfn[i])
          tarjan(i);
        }
    
        for(int i=1;i<=m;i++)
        {
        if(root[edge[i].u]!=root[edge[i].v])
        in[root[edge[i].v]]++;
        }
        for(int i=1;i<=n;i++)
        {
           int r=root[i];
           if(in[r]==0)
            ans.push_back(r);
    
        }
        sort(ans.begin(),ans.end());
        ans.erase(unique(ans.begin(),ans.end()),ans.end());
        cout<<ans.size()<<endl;
        for(int i=0;i<ans.size();i++)
        i==0?cout<<ans[i]:cout<<" "<<ans[i];
        cout<<endl;
        return 0;
    }
  • 相关阅读:
    Java 中常用的数据源
    Restful风格API接口开发springMVC篇
    Maven的作用到底是什么
    Java中常用的数据源
    数据库死锁问题 及 解决方法
    string中执行sql语句
    提高mysql千万级大数据SQL查询优化30条经验
    JAVA对象转换JSON
    oracle分页查询
    jdk8环境变量 jdk8图解安装 java8安装
  • 原文地址:https://www.cnblogs.com/a249189046/p/8954347.html
Copyright © 2011-2022 走看看