首先對於乙個強聯通分量內的所有牛來說,他們彼此都認為對方受歡迎,且對於這個強聯通分量內的牛a來說,假設它認為不在這個強連通分量內的一頭牛b是受歡迎的,那麼這個強聯通分量內的所有牛都認為牛b受歡迎。
我們用tarjan演算法求一遍scc,把乙個scc縮成乙個點,並新增連線不同scc的邊,注意這條邊是一條反向邊,本來的邊由a->b,我們要新增的這條邊由scc[b]->scc[a],這樣做是為了方便之後的dfs,最後得到乙個dag。
接下來我們在這個dag上從所有入度為0的scc開始dfs,並記錄dfs過程中訪問到的scc個數記為cnt,如果dfs結束後cnt==scc_cnt,代表所有scc都認為這個scc是受歡迎的,則所有牛都認為這個scc內的牛是受歡迎的,累計牛的個數進答案即可。
我們只需要從入度為0的scc開始dfs,是因為假設有一條邊scc_a->scc_b,代表scc_b認為scc_a是受歡迎的,又因為圖是dag,所以scc_a一定不認為scc_b是受歡迎的,那麼scc_b一定無法達到被所有牛認為是受歡迎的條件,所以我們證明了入度不為0的scc一定不會是解。
// q.c#include#include#include#include#include#includeusing namespace std;
const int m=10000+10;
int n,m,ans,cnt1,cnt2,dc,scc_cnt,scc[m],h1[m],h2[m],w[m],pre[m],low[m],in[m],out[m];
bool vis[m];
stacks;
struct edge
}ed1[m*5],ed2[m*5];
void add_edge(int a,int b,bool flag)
void dfs1(int u) else if(!scc[p.v])
low[u]=min(low[u],low[p.v]);
} if(low[u]==pre[u]) }}
void dfs2(int u,int &d)
int main()
for(int i=1;i<=n;i++)
if(!pre[i]) dfs1(i);
for(int i=1;i<=n;i++) w[scc[i]]++;
for(int i=1;i<=cnt1;i++)
for(int i=1;i<=scc_cnt;i++)
if(!in[i])
printf("%d\n",ans);
return 0;
}
HAOI2006 受歡迎的牛
題目 分析 tarjan縮點。最後如果只有乙個出度為0的點,則答案就是這個點包含的牛數,否則為0.一開始最後統計的時候寫了dfs,後來發現是錯誤的,反例 include include include include include using namespace std const int tma...
HAOI2006 受歡迎的牛
這個就是強連通,計算出度為0的點就好 也沒森麼其它好講的啦 提交傳送們 description 每一頭牛的願望就是變成一頭最受歡迎的牛。現在有n頭牛,給你m對整數 a,b 表示牛a認為牛b受歡迎。這種關係是具有傳遞性的,如果a認為b受歡迎,b認為c受歡迎,那麼牛a也認為牛c受歡迎。你的任務是求出有多...
HAOI2006 受歡迎的牛
haoi2006 受歡迎的牛 每一頭牛的願望就是變成一頭最受歡迎的牛。現在有n頭牛,給你m對整數 a,b 表示牛 a 認為牛 b受歡迎。這種關係是具有傳遞性的,如果a認為b受歡迎,b認為c受歡迎,那麼牛a也認為牛c受歡迎。你的任務是求出有多少頭牛被所有的牛認為是受歡迎的。第1行兩個整數n,m 接下來...