首页 > 其他分享 >求图里面能被所有点走到的点有几个

求图里面能被所有点走到的点有几个

时间:2022-08-30 20:59:05浏览次数:70  
标签:里面 几个 ++ stk int dfn low 联通 求图

https://www.acwing.com/problem/content/1176/

对于拓扑图 如果某一个点的出度为0 那么这个点就能被其他所有点到达
但是题目里所给的点不是拓扑图 所以我们需要缩点
强联通分量里面的所有点互相到达 外面的点到这个强联通的点可以到达
所以就可以强联通分量上的点就是我们需要的点了

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e4+10,M=5e4+10;
int n,m;
int h[N], e[M], ne[M], idx;
int dfn[N],low[N],timestamp;//low 从u开始走能遍历到的最小时间戳
int stk[N],top;
//不需要建立出缩小完后的点
bool in_stk[N];//表示是不是在栈当中
int id[N],scc_cnt,Size[N];//表示每个点都是哪个强联通分量里面的 有多少个强联通分量 每个强联通分量的大小是
int dout[N];
void add(int a, int b)  // 添加一条边a->b
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
void tarjan(int u){
    dfn[u]=low[u]=++timestamp;//记录时间戳
    stk[++top]=u,in_stk[u]=true;
    for (int i = h[u]; ~i ; i =ne[i] ){
        int j=e[i];
        if(!dfn[j]){//当前点没有遍历过
            tarjan(j);
            low[u]=min(low[u],low[j]);//如果j比自己还小那么说明能走到上面
        }
        ////如果j在栈中 说明还没出栈 而且dfs序比当前点u小 要么这个横叉 要么指回去 两种情况j的dfs序都小 所以要更新
        else if(in_stk[j]) low[u]=min(low[u],dfn[j]);//在站里面的
        
    }

    if(dfn[u]==low[u])//如果自己就是最上面的点 那么自己就是强联通分量的点
    {
        ++scc_cnt;
        int y;
        do{
            y=stk[top--];//取出栈里面的点
            in_stk[y]=false;
            id[y]=scc_cnt;
            Size[scc_cnt]++;
        }while(y!=u);//因为栈中的元素dfs序比u大 所以我们只要吧dfs序打的点pop 当y'u的时候 点u所在的所有强联通分量都标记了id
    }
}
int main()
{
    cin >> n>>m;
    memset(h, -1, sizeof h);
    while (m -- ){
        int a,b;cin>>a>>b;
        add(a, b);
    }
    //遍历所有点 如果当前点没有遍历过就遍历
    for (int i = 1; i <= n; i ++ ){
        if(!dfn[i])
            tarjan(i);
    }
    for (int i = 1; i <= n; i ++ ){
        for (int j = h[i]; ~j; j=ne[j] )//遍历所有边
        {
            int k=e[j];
            int a=id[i],b=id[k];//a b表示边的两个端点的联通编号 
            if(a!=b){//说明这个点的边还会使用到缩点之后的边
                dout[a]++;//a走到b
            }
        }
    }
    
    int zeros=0,sum=0;
    for (int i = 1; i <= scc_cnt; i ++ ){//对于缩点后的点
        if(!dout[i]){//如果出度为0
            zeros++;//出度为0的点+1
            sum+=Size[i];
            if(zeros>1){//题目结论:如果多于一个点的出度为0 那么久不回有任何一个
                sum=0;
                break;
            }
        }
    }
    printf("%d\n",sum);
    return 0;
}

标签:里面,几个,++,stk,int,dfn,low,联通,求图
From: https://www.cnblogs.com/liang302/p/16640750.html

相关文章

  • centos下mysql 最新版终于安装成功!备份一下几个关键地方
    我本来只是为了搭建简单的LAMP环境,亲自动手,却发现有这么多的问题会发生。(bydefault7#zbphp.com)很多地方给的安装Mysql的提示是通过yum一键安装。shell命令如下:yumins......
  • Python批量校验两个文件夹里面的文件MD5
    importbase64importhashlibimportosg_origin_path="【目录】"g_target_path="【目录】"defget_file_md5(filepath):f=open(filepath,'rb')md5......
  • 一个字符占几个字节
    1个汉字字符存储需要2个字节,1个英文字符存储需要1个字节。ASCII是一个字节,Unicode是两个字节。Java的字符是Unicode的,所以是两个字节。字符是指计算机中使用的字母、数字、......
  • 推荐几个不错的 CSS 工具,持续收录!
    原文链接:推荐几个不错的CSS工具,持续收录!NeumorphismNeumorphism是一个很棒的工具,可以根据你的喜好选择颜色、编辑大小、半径、距离等为你的设计生成UICSS代码......
  • 几个官网
    Indexof/dist/tomcat http://archive.apache.org/dist/tomcat/ Java软件|Oracle中国 https://www.oracle.com/cn/java/ MySQLhttps://www.mysql.com/d......
  • Spring 最常用的几个注解
    大家都知道Spring严重依赖注解。实际开发的时候,我们用得最多的可能就是下面几个注解了。注解用途@Component最最普通的注解,表示这个类可以被注入到Spring容......
  • airtest截图后放在allure报告里面。
    #需要导入的包fromairtest.aircvimport*fromairtest.aircv.utilsimportcv2_2_pilscreen1=G.DEVICE.snapshot()screen1=aircv.crop_image(screen1,(100,1......
  • python中常见的几个函数
    functionuselen()用来求元组利润表或者字符串等的长度str()将数据转化成字符串类型......
  • 怎么把手机相册中的视频导到便签里面
    随着智能手机影像功能的发展,现在越来越多的网友会选择使用手机来拍照或录视频记录生活。不过随着时间的推移,我们的手机相册中会保存很多的视频文件,想要查找某个视频时就非......
  • 一个字符串,里面必须有下划线,怎么写正则
    https://zhidao.baidu.com/question/2119997888128668107.html.*_.*如上即可,任意个字符后跟一个下划线然后再任意个字符,有下划线才能匹配,其余字符随意......