傳送門啦
這個題就是tarjan強連通分量與入度的例題了。
思路:利用縮點的思想,先預處理一下所有的強連通分量,然後把每個強連通分量內的所有節點看做乙個節點,然後處理一張新圖,然後檢查每個點的入度,然後取入度為 0 的點(縮點後)的個數,即為資訊出發點。
可能有人想問為什麼??
大體說明一下:
1.充分性證明:如果入度為 0 的點不是資訊出發點,那麼這個點必定不會接收到任何節點發出的資訊,因為它的入度為 0 。
還是先明確一下各個陣列的意思吧:
dfn[i]:i點的時間戳
low[i],表示這個點以及其子孫節點連的所有點中dfn最小的值
stack,表示當前所有可能能構成是強連通分量的點。
ins[i],表示 i 是否在stack[ ]陣列中
num[i],表示第 i 個強連通分量中有多少個點
belong[i],表示第 i 點在哪乙個強連通分量裡
in[i]:表示第 i 個強連通分量的入度是多少。
以下就是怎麼處理入度:
for(int i=1;i<=m;i++)
解釋一下:
列舉邊,比較這條邊起點和終點是否在同乙個強連通分量中,如果不在,這條邊終點的入度++
ac**:
#include #include #include #include using namespace std;
const int maxn = 1e5 + 5;
const int maxm = 5e5 + 6;
int n,m,u,v;
int head[maxn],tot;
int dfn[maxn],low[maxn],ind;
int stack[maxn],top,belong[maxn],num[maxn],cnt;
int in[maxn];//表示某個點的入度
int ans;
bool ins[maxn];
struct edgeedge[maxm];
void add(int u,int v)
int read()
while(ch >= '0' && ch <= '9')
return x * f;
}void tarjan(int x)
} int k;
if(dfn[x] == low[x]) while(k != x); }}
int main()
for(int i = 1;i <= n ;++i) belong[i] = i;
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=m;i++)
for(int i=1;i<=cnt;i++)
if(in[i] == 0)
ans++;
printf("%d\n",ans);
return 0;
}
(tarjan)洛谷 P2002 訊息擴散
思路 tarjan縮點,強連通分量裡的點肯定是可以互相到達的,那縮完 度為0的點數就是答案了 有n個城市,中間有單向道路連線,訊息會沿著道路擴散,現在給出n個城市及其之間的道路,問至少需要在幾個城市發布訊息才能讓這所有n個城市都得到訊息。第一行兩個整數n,m表示n個城市,m條單向道路。以下m行,每行...
P2002 訊息擴散
本場比賽第一題,給個簡單的吧,這 100 分先拿著。有n個城市,中間有單向道路連線,訊息會沿著道路擴散,現在給出n個城市及其之間的道路,問至少需要在幾個城市發布訊息才能讓這所有n個城市都得到訊息。輸入格式 第一行兩個整數n,m表示n個城市,m條單向道路。以下m行,每行兩個整數b,e表示有一條從b到e...
P2002 訊息擴散
本場比賽第一題,給個簡單的吧,這 100 分先拿著。有n個城市,中間有單向道路連線,訊息會沿著道路擴散,現在給出n個城市及其之間的道路,問至少需要在幾個城市發布訊息才能讓這所有n個城市都得到訊息。輸入格式 第一行兩個整數n,m表示n個城市,m條單向道路。以下m行,每行兩個整數b,e表示有一條從b到e...