洛谷P2002訊息擴散

2022-04-05 22:08:52 字數 1525 閱讀 6228

傳送門啦

這個題就是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...