題解 P2002 【消息擴散】

有n個城市,中間有單向道路連接,消息會沿着道路擴散,現在給出n個城市及其之間的道路,問至少需要在幾個城市發佈消息才能讓這所有n個城市都得到消息。

前置知識:

分析

會了強聯通分量以後呢,我們可以開始寫這道題了。首先這道題不是一個 DAGDAG 我們應該先縮點,把這個圖變成一個 DAGDAG

變成 DAGDAG 就好了,我們就可以記錄每個點的入度,答案即爲所有入度爲 00 的點的個數。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>inline void read(T &FF){
	T RR=1;FF=0;char CH=getchar();
	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
	FF*=RR;
}
template<typename T>inline void write(T x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar('0'+x%10);
}
const int MAXN=1e6+10,MAXM=1e6+10;
int s[MAXN], stop,dfn[MAXN],low[MAXN],scccnt, sccnum[MAXN],dfscnt,tot,he[MAXN],ne[MAXM<<1],ed[MAXM<<1],n,x,y,de[MAXN],ans,m;
void add(int x,int y){
	ed[++tot]=y;
	ne[tot]=he[x];
	he[x]=tot;
}
inline void tarjan(int now){
	dfn[now] = low[now] = ++dfscnt;
	s[stop++] = now;
	for (int i = he[now]; i; i = ne[i]){
		if(!dfn[ed[i]]){
			tarjan(ed[i]);
			low[now] = min(low[now], low[ed[i]]);
		}else if(!sccnum[ed[i]]) {
			low[now] = min(low[now], dfn[ed[i]]);
		}
	}

	if (dfn[now]==low[now]){
		scccnt++;
		do {
			sccnum[s[--stop]]=scccnt;
		}while(s[stop]!=now);
	}
}
int main(){
	read(n);read(m);
	for(int i=1;i<=m;i++){
		read(x);read(y);
		add(x,y);
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i])tarjan(i);
	for(int i=1;i<=n;i++)
		for(int j=he[i];j;j=ne[j])
			if(sccnum[i]!=sccnum[ed[j]])de[sccnum[ed[j]]]++;
	for(int i=1;i<=scccnt;i++)
		if(!de[i])ans++;
	cout<<ans;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章