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

P2002 消息擴散

using div turn 限制 都得 cnblogs 16px int left

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的(因為入度為0的點必須得知道消息,否則沒有消息來源。)

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<stack>
 4 using
namespace std; 5 6 const int MAXN = 100100; 7 struct Edge{ 8 int to,nxt; 9 }e[500100]; 10 int head[MAXN],dfn[MAXN],low[MAXN],bel[MAXN],t[MAXN],x[500100],y[500100]; 11 bool vis[MAXN]; 12 int cnt,n,m,tot,ans,num; 13 stack<int>s; 14 15 void add(int u,int v) 16 { 17 ++cnt; 18 e[cnt].to = v;
19 e[cnt].nxt = head[u]; 20 head[u] = cnt; 21 } 22 void tarjan(int u) 23 { 24 low[u] = dfn[u] = ++tot; 25 s.push(u); 26 vis[u] = true ; 27 for (int i=head[u]; i; i=e[i].nxt) 28 { 29 int v = e[i].to; 30 if (!dfn[v]) 31 { 32 tarjan(v); 33 low[u] = min(low[u],low[v]); 34 } 35 else if (vis[v]) low[u] = min(low[u],low[v]); 36 } 37 if (dfn[u]==low[u]) 38 { 39 int now = -1; 40 num++; 41 while (now!=u) 42 { 43 now = s.top(); 44 s.pop(); 45 bel[now] = num; 46 vis[now] = false ; 47 } 48 } 49 } 50 int main() 51 { 52 scanf("%d%d",&n,&m); 53 for (int i=1; i<=m; ++i) 54 { 55 scanf("%d%d",&x[i],&y[i]); 56 add(x[i],y[i]); 57 } 58 for (int i=1; i<=n; ++i) 59 if (!dfn[i]) tarjan(i); 60 for (int i=1; i<=m; ++i) 61 { 62 if (bel[x[i]]!=bel[y[i]]) 63 t[bel[y[i]]]++; 64 } 65 for (int i=1; i<=num; ++i) 66 if (t[i]==0) ans++; 67 printf("%d",ans); 68 return 0; 69 }

P2002 消息擴散