消息扩散

题目背景

本场比赛第一题,给个简单的吧,这 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号城市中发布消息。

 

分析:

本题很简单???我做了好多遍。。。先%%%牛的传说帮我改对了这题。

本题思路就是求强连通分量,但是去重很麻烦,最后看到了题解判断入度才豁然开朗em。。。

 

CODE:

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<stack>
 4 #include<cstring>
 5 using namespace std;
 6 const int M=5000005;
 7 int n,m;
 8 int next[M],to[M],head[M];
 9 int ans;
10 int du[M];
11 inline int get(){
12     char c=getchar();
13     int res=0;
14     while (c>'9'||c<'0') c=getchar();
15     while (c<='9'&&c>='0') {
16         res=(res<<3)+(res<<1)+c-'0';
17         c=getchar();
18     }
19     return res;
20 }
21 int tot;
22 inline void add(int u,int v){
23     next[++tot]=head[u];
24     head[u]=tot;
25     to[tot]=v;
26 }
27 int low[M],dfn[M];
28 bool vis[M];
29 int in,now;
30 stack<int> q;
31 int f[M];
32 void tarjan(int u){
33     dfn[u]=low[u]=++in;
34     q.push(u);
35     vis[u]=true;
36     for (int i=head[u];i;i=next[i]){
37         int v=to[i];
38         if (dfn[v]==-1){
39             tarjan(v);
40             low[u]=min(low[u],low[v]);
41         }
42         else if (vis[v]) low[u]=min(low[u],dfn[v]);
43     }
44     int v;
45     if (dfn[u]==low[u]){
46         now++;
47         do {
48             v=q.top();
49             f[v]=now;
50             vis[v]=false;
51             q.pop();
52         }while (u!=v);
53     }
54 }
55 int main(){
56     n=get(),m=get();
57     for (int i=1;i<=m;i++){
58         int x=get(),y=get();
59         if (x!=y) add(x,y);
60     }
61     memset(vis,false,sizeof(vis));
62     memset(dfn,-1,sizeof(dfn));
63     for (int i=1;i<=n;i++)
64         if (dfn[i]==-1) tarjan(i);
65     for (int i=1;i<=n;i++){
66         for (int j=head[i];j;j=next[j]){
67             int z=to[j];
68             if (f[i]!=f[z]) du[f[z]]++;
69         }
70     }
71     //cout<<now<<endl;
72     for (int i=1;i<=now;i++){
73         //cout<<du[i]<<endl;
74         ans+=(du[i]==0);
75     }
76     cout<<ans<<endl;
77     return 0;
78 }

 

posted @ 2019-09-17 01:23  Sword_Art_Online  阅读(223)  评论(0编辑  收藏  举报