受歡迎的牛(tarjan)

2021-10-06 05:31:20 字數 1553 閱讀 1926

題目連線:

每一頭牛的願望就是變成一頭最受歡迎的牛。現在有n頭牛,給你m對整數(a,b),表示牛a認為牛b受歡迎。

這種關係是具有傳遞性的,如果a認為b受歡迎,b認為c受歡迎,那麼牛a也認為牛c受歡迎。

你的任務是求出有多少頭牛被所有的牛認為是受歡迎的。

第一行兩個數n,m。

接下來m行,每行兩個數a,b,意思是a認為b是受歡迎的(給出的資訊有可能重複,即有可能出現多個a,b)

乙個數,即有多少頭牛被所有的牛認為是受歡迎的。
示例1

複製3 3 1 2 2 1 2 3

3 3

1 22 1

2 3

複製1

1
思路:用tarjan求出連通分量的個數,然後對每個聯通分量求出度,要想被所有的牛歡迎,則該牛所在的連通分量的出度必為0,並且只能有乙個出度為0的連通分量,自己可以嘗試畫一下。答案就是出度為0 的那個連通分量中的牛。

那看**吧

關於鏈式前向星的存圖方式請看(這個真的很好用,比較快):

code:

#include#include#include#include#include#define inf 0x3f3f3f3f

using namespace std;

typedef long long ll;

const int n=3e5+10;

int n,m;

int out[n];//每個連通分量的出度

int low[n],dfn[n];//遍歷順序和時間戳

int idex,id,cnt;

bool instack[n];//判斷是否還在棧中

stacks;

int head[n],e[n],ne[n];//鏈式前向星存圖更加快

int pre[n];//存每個點所在哪個連通分量

int ans;

int res;

void tarjan(int u)

else if(instack[v]) low[u]=min(low[u],dfn[v]);//如果在棧中就更新該點的時間戳

} // 回溯找出連通分量

if(low[u]==dfn[u])while(u!=v);

} }//對所有的點進行tarjan

void scc()

}//存圖

void add(int u,int v)

int main()

scc();

for(int i=1;i<=n;i++)

} }int num=0;

for(int i=1;i<=id;i++)

} // 當出度不為1的時候不存在任何牛被歡迎,直接輸出0即可

if(res==0||res>=2)

//num這個連通分量所包含牛的個數

for(int i=1;i<=n;i++)

cout

}

tarjan 受歡迎的牛

題 既然愛慕關係可以傳遞,那麼將互相可達的某幾個點縮成乙個點,就能簡化原圖了,那麼很自然想到tarjan求強連通分量 那麼就只需找到可以被所有縮點遍歷到的那個縮點 再輸出它所含的點數就行了 先用tarjan將所有聯通分量進行縮點,縮點後考慮出度為0的點的個數 1 個數大於1的時候,顯然不存在受歡迎的...

受歡迎的牛 Tarjan

每一頭牛的願望就是變成一頭最受歡迎的牛。現在有 頭牛,給你 對整數 表示牛 認為牛 受歡迎。這種關係是具有傳遞性的,如果 認為 受歡迎,認為 受歡迎,那麼牛 也認為牛 受歡迎。你的任務是求出有多少頭牛被除自己之外的所有牛認為是受歡迎的。輸入格式 第一行兩個數 接下來 行,每行兩個數 意思是 認為 是...

2017 07 14 Tarjan(受歡迎的牛)

include include include include include include include include include define mm 50002 define nn 10002 using namespace std int n,m,cnt,sign,top,tot i...