1. 程式人生 > >洛谷—— P2002 消息擴散

洛谷—— P2002 消息擴散

中間 消息 個數 連通 輸入輸出 現在 www 限制 cnblogs

https://www.luogu.org/problem/show?pid=2002

題目背景

本場比賽第一題,給個簡單的吧,這 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號城市中發布消息。

入度為0的強連通個數、

 1 #include <cstdio>
 2 
 3 #define min(a,b) (a<b?a:b)
 4 inline void read(int &x)
 5 {
 6     x=0; register char ch=getchar();
7 for(; ch>9||ch<0; ) ch=getchar(); 8 for(; ch>=0&&ch<=9; ch=getchar()) x=x*10+ch-0; 9 } 10 const int N(100005); 11 const int M(500005); 12 int head[N],sumedge; 13 struct Edge { 14 int v,next; 15 Edge(int v=0,int next=0):v(v),next(next){} 16 }edge[M]; 17 inline void
ins(int u,int v) 18 { 19 edge[++sumedge]=Edge(v,head[u]); head[u]=sumedge; 20 } 21 22 int tim,dfn[N],low[N]; 23 int top,Stack[N],instack[N]; 24 int sumcol,col[N],ans,rd[N]; 25 void Tarjan(int u) 26 { 27 low[u]=dfn[u]=++tim; 28 Stack[++top]=u; 29 instack[u]=true; 30 for(int v,i=head[u]; i; i=edge[i].next) 31 { 32 v=edge[i].v; 33 if(!dfn[v]) Tarjan(v),low[u]=min(low[u],low[v]); 34 else if(instack[v]) low[u]=min(low[u],dfn[v]); 35 } 36 if(low[u]==dfn[u]) 37 { 38 col[u]=++sumcol; 39 for(; Stack[top]!=u; top--) 40 { 41 col[Stack[top]]=sumcol; 42 instack[Stack[top]]=false; 43 } 44 instack[u]=0; top--; 45 } 46 } 47 48 int Presist() 49 { 50 int n,m; read(n),read(m); 51 for(int u,v,i=1; i<=m; ++i) 52 read(u),read(v),ins(u,v); 53 for(int i=1; i<=n; ++i) 54 if(!dfn[i]) Tarjan(i); 55 for(int v,u=1; u<=n; ++u) 56 for(int i=head[u]; i; i=edge[i].next) 57 { 58 v=edge[i].v; 59 if(col[u]!=col[v]) rd[col[v]]++; 60 } 61 for(int i=1; i<=sumcol; ++i) if(!rd[i]) ans++; 62 printf("%d\n",ans); 63 return 0; 64 } 65 66 int Aptal=Presist(); 67 int main(int argc,char*argv[]){;}

洛谷—— P2002 消息擴散