zoukankan      html  css  js  c++  java
  • luogu P2002 消息扩散

    题目背景

    本场比赛第一题,给个简单的吧,这 100 分先拿着。

    题目描述

    有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市发布消息才能让这所有n个城市都得到消息。

    输入输出格式

    输入格式:

    第一行两个整数n,m表示n个城市,m条单向道路。

    以下m行,每行两个整数b,e表示有一条从b到e的道路,道路可以重复或存在自环。

    输出格式:

    一行一个整数,表示至少要在几个城市中发布消息。

    输入输出样例

    输入样例#1:
    5 4
    1 2
    2 1
    2 3
    5 1
    
    输出样例#1:
    2
    

    说明

    【数据范围】

    对于20%的数据,n≤200;

    对于40%的数据,n≤2,000;

    对于100%的数据,n≤100,000,m≤500,000.

    【限制】

    时间限制:1s,内存限制:256M

    【注释】

    样例中在4,5号城市中发布消息。

     tarjan算法将每个强连通分量缩成点,记录原先的每个点缩入了哪个点

    缩完之后,扫描每条边,判断如果终点和起点所在的分量不同,标记终点

    最后扫描为标记的的点计数器++也就是(入度为0的点)

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    int n,m,topp;
    #define N 100006
    struct sta{
        int sz[100001];
        int top(){return sz[topp];}
        void push(int x){sz[++topp]=x;}
        void pop(){if(topp>0)topp--;}
    }stack;
    
    struct node{
        int v,next;
    }edge[N*5];int head[N],num;
    int dfn[N],low[N],color[N];bool vis[N];
    
    void add_edge(int x,int y)
    {
        edge[++num].v=y;edge[num].next=head[x];head[x]=num;
    }
    int cnt;
    void tarjan(int x)
    {
        dfn[x]=low[x]=++num;
        stack.push(x);
        vis[x]=1;
        for(int i=head[x];i;i=edge[i].next)
        {
            int v=edge[i].v;
            if(!dfn[v])
            {
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else if(vis[v])low[x]=min(low[x],dfn[v]);    
        }
        if(dfn[x]==low[x])
        {
            ++cnt;
            int r;
            do{
                r=stack.top();
                color[r]=cnt;
                vis[r]=0;
                stack.pop();
            }while(r!=x);
        }
        return ;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int a,b;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);add_edge(a,b);
        }
        num=0;
        for(int i=1;i<=n;i++)
        if(!dfn[i])tarjan(i);
        memset(vis,0,sizeof vis);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].next)
            {
                int v=edge[j].v;
                if(color[i]!=color[v])
                {
                    vis[color[v]]=1;
                }
            }
        }
        int ans=0;
        for(int i=1;i<=cnt;i++)
            if(!vis[i]) ans++;
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    C/C++多文件之间的变量定义
    PKU POJ 2186 Popular Cows 强连通分量
    重载函数
    ZOJ 2763 Prison Break
    201357 训练赛总结
    hdu 4467 Graph 构造
    201356 训练赛总结
    201353 NEERC 2012, Eastern subregional contest
    2013512 CF 183 总结
    一道动态规划
  • 原文地址:https://www.cnblogs.com/sssy/p/7074426.html
Copyright © 2011-2022 走看看