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

    题目描述

    给出一个 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
    题意
    如上
    题解
    求有向图的最大强连通加上缩点,输出缩完后每个强连通子集的最小的点即可
    强连通分量:有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量
    缩点:因为强连通分量中的每两个点都是强连通的,可以将一个强连通分量当做一个超级点
    代码
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=1e5+5;
     4 vector<int>G[N],id[N];
     5 
     6 int low[N],dfn[N],instack[N],st[N],tot,cnt,scc,p;
     7 int belong[N],in[N];
     8 void tarjan(int u)
     9 {
    10     int v;
    11     low[u]=dfn[u]=++tot;//时间戳
    12     st[++cnt]=u;//入栈
    13     instack[u]=1;
    14     for(int i=0;i<G[u].size();i++)
    15     {
    16         v=G[u][i];
    17         if(!dfn[v])//是否已经访问
    18         {
    19             tarjan(v);
    20             low[u]=min(low[u],low[v]);
    21         }
    22         else if(instack[v])//已经访问过并且在栈里
    23         {
    24             low[u]=min(low[u],dfn[v]);
    25         }
    26     }
    27     if(low[u]==dfn[u])
    28     {
    29         scc++;//强连通
    30         do{
    31             v=st[cnt--];//出栈
    32             instack[v]=0;//v出栈后
    33             belong[v]=scc;//v属于哪个强连通1-scc
    34             id[scc].push_back(v);//当前强连通的子集
    35         }while(u!=v);
    36     }
    37 }
    38 int main()
    39 {
    40     int n,m,u[N],v[N];
    41     scanf("%d%d",&n,&m);
    42     for(int i=1;i<=m;i++)
    43     {
    44         scanf("%d%d",&u[i],&v[i]);
    45         G[u[i]].push_back(v[i]);
    46     }
    47     for(int i=1;i<=n;i++)//求所有强连通
    48         if(!dfn[i])//是否已经访问过
    49             tarjan(i);
    50     for(int i=1;i<=m;i++)//缩点
    51     {
    52         if(belong[u[i]]==belong[v[i]])continue;
    53         in[belong[v[i]]]++;
    54     }
    55     for(int i=1;i<=scc;i++)
    56         sort(id[i].begin(),id[i].end());
    57     vector<int> res;
    58     for(int i=1;i<=scc;i++)
    59         if(!in[i])
    60             res.push_back(id[i][0]);
    61     printf("%d
    %d",res.size(),res[0]);
    62     for(int i=1;i<res.size();i++)
    63         printf(" %d",res[i]);
    64     return 0;
    65 }
  • 相关阅读:
    规约先行-(六)并发处理
    MySQL选择合适的方式存储时间
    规约先行-(五)集合处理
    规约先行-(四)OOP 规约
    12.20-LaTex git workflow
    6.25-ROS 软件度量
    6.19-rosdoc_lite and 文档构建工具
    12.27-ros-decision making
    12.3-分级并发有限状态机-SMACH
    12.07-rostest学习
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/8899331.html
Copyright © 2011-2022 走看看