(tarjan)洛谷 P2002 消息扩散

思路:tarjan缩点,强连通分量里的点肯定是可以互相到达的,那缩完后入度为0的点数就是答案了

题目描述

有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号城市中发布消息。

#include <cstdio>
#include<iostream>
#include <cstring>
#include <algorithm>
#include <stack>
#include<set>
#include<vector>
using namespace std;
#define ll long long
const int maxn=505000;
stack<int>q;
set<int>ans;
vector<int>a[maxn];
int cnt,n,m,head[maxn],dfn[maxn],low[maxn],co[maxn],tot,id,out[maxn],root;
struct Edge
{
    int to,next;
}e[maxn];
void add(int u,int v)
{
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
void init()
{
    ans.clear();
    for(int i=0;i<maxn;i++) a[i].clear();
    memset(out,0,sizeof(out));
    memset(co,0,sizeof(co));
    memset(head,-1,sizeof(head));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    while(!q.empty()) q.pop();
    cnt=0;id=0,tot=0;
}
void tarjan(int u)
{
    q.push(u);
    dfn[u]=low[u]=++tot;int ch=0;
    for(int i=head[u];i!=-1;i=e[i].next)
    {
        int v=e[i].to;
        if(!dfn[v])
        {
            ch++;
            tarjan(v);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u]&&u!=root) ans.insert(u);
        }
        else if(!co[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(root==u&&ch>=2) ans.insert(u);
    if(low[u]==dfn[u])
    {
        id++;
        while(q.top()!=u)
        {
            int x=q.top();
            q.pop();
            co[x]=id;
        }
        co[u]=id;
        q.pop();
    }
}
int d[maxn];
int main()
{
    scanf("%d %d",&n,&m);
    init();
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d %d",&u,&v);
        add(u,v);//add(v,u);
    }
    for(int i=1;i<=n;i++)
    {
        if(dfn[i]==0) {
                root=i;
                tarjan(i);
        }
    }
    /*for(int i=1;i<=n;i++)
    {
        printf("co[%d]=%d\n",i,co[i]);
    }*/
    for(int i=1;i<=n;i++) a[co[i]].push_back(i);
    for(int i=1;i<=id;i++)
    {
        for(int k=0;k<a[i].size();k++)
        {
            int u=a[i][k];
            for(int j=head[u];j!=-1;j=e[j].next)
            {
                int v=e[j].to;
                if(co[v]==i) continue;
                d[co[v]]++;
            }
        }
    }
    int w=0;
    for(int i=1;i<=id;i++) w+=(d[i]==0);
    printf("%d\n",w);
}

猜你喜欢

转载自blog.csdn.net/qq_43497140/article/details/106959996