消息扩散
题目背景
本场比赛第一题,给个简单的吧,这 100 分先拿着。
题目描述
有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市发布消息才能让这所有n个城市都得到消息。
输入输出格式
输入格式:
第一行两个整数n,m表示n个城市,m条单向道路。
以下m行,每行两个整数b,e表示有一条从b到e的道路,道路可以重复或存在自环。
输出格式:
一行一个整数,表示至少要在几个城市中发布消息。
输入输出样例
说明
【数据范围】
对于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 }