POJ 2186 Popular Cows (korasaju 演算法)
阿新 • • 發佈:2020-07-29
Description
每頭牛都想成為牛群中的紅人。給定n頭牛和m個有序對(a,b),(a,b)表示牛a認為牛b是紅人。該關係有傳遞性,所以如果牛a認為牛b是紅人,牛b認為牛c是紅人,那麼牛a認為牛c也是紅人。求被其他所有牛認為是紅人的牛的總數
Input
第一行兩個整數n和m表示牛數和關係數,之後m行每行兩個整數a和b表示牛a認為牛b是紅人
Output
輸出被其他所有牛認為是紅人的牛的個數
Sample Input
3 3
1 2
2 1
2 3
Sample Output
1
Solution
題意:有N頭牛 每一頭牛都夢想著成為popular cow,(但這是不可能滴) 有m組仰慕的關係,仰慕有傳遞性 比如說A覺得B是popular and B thinks C is popular, then A thinks C is popalur also;
現在問有多少頭牛是會被其他牛都仰慕。
思路:求強連通分量,縮成點 點內的頭當然是相互仰慕的咯!! 然後求新的圖 的出度 出度也0的點就會被所有牛仰慕 算出出度為0的強連通分量裡點的個數就OK了,注意 可能有多個出度為0的點,這時輸出0(不滿足要求) 剛學korasaju 演算法,所以用它做
Code
//Kosaraju 演算法 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int VM=10010; const int EM=50010; struct Edge{ int to,nxt; }edge1[EM],edge2[EM]; int head1[VM],head2[VM],n,cnt; int scc_id[VM],vis[VM],order[VM],k,scc; int indeg[VM],outdeg[VM]; void addedge(int cu,int cv){ edge1[cnt].to=cv; edge1[cnt].nxt=head1[cu]; head1[cu]=cnt; edge2[cnt].to=cu; edge2[cnt].nxt=head2[cv]; head2[cv]=cnt++; } void DFS(int u){ for(int i=head1[u];i!=-1;i=edge1[i].nxt){ int v=edge1[i].to; if(!vis[v]){ vis[v]=1; DFS(v); } } order[++k]=u; } void reDFS(int u){ for(int i=head2[u];i!=-1;i=edge2[i].nxt){ int v=edge2[i].to; if(!scc_id[v]){ scc_id[v]=scc; reDFS(v); } } } void Korasaju(){ int i,u; k=scc=0; memset(vis,0,sizeof(vis)); memset(scc_id,0,sizeof(scc)); memset(order,0,sizeof(order)); for(u=1;u<=n;u++) if(!vis[u]){ vis[u]=1; DFS(u); } for(i=n;i>0;i--){ u=order[i]; if(!scc_id[u]){ scc_id[u]=++scc; reDFS(u); } } } void Count_deg(){ memset(indeg,0,sizeof(indeg)); memset(outdeg,0,sizeof(outdeg)); for(int u=1;u<=n;u++) for(int i=head1[u];i!=-1;i=edge1[i].nxt){ int v=edge1[i].to; if(scc_id[u]!=scc_id[v]){ indeg[scc_id[v]]++; outdeg[scc_id[u]]++; } } } int main(){ //freopen("input.txt","r",stdin); int m; while(~scanf("%d%d",&n,&m)){ memset(head1,-1,sizeof(head1)); memset(head2,-1,sizeof(head2)); cnt=0; int u,v; while(m--){ scanf("%d%d",&u,&v); addedge(u,v); } Korasaju(); Count_deg(); int count=0,loc; for(int i=1;i<=scc;i++) if(outdeg[i]==0){ count++; loc=i; } if(count>1) printf("0\n"); else{ count=0; for(u=1;u<=n;u++) if(scc_id[u]==loc) count++; printf("%d\n",count); } } return 0; }