Papa的朋友圈(原POJ 2186)Tarjan
阿新 • • 發佈:2018-08-04
iostream idt urn pac ros stdio.h eight div fin
題目描述
Papa朋友圈裏的每一個人都夢想成為朋友圈裏的網紅。被所有人喜歡的人就是一個網紅。Papa所有的朋友都是自戀狂,每個人總是喜歡自己的。人與人之間的“喜歡”是可以傳遞的——如果A喜
歡B,B喜歡C,那麽A也喜歡C。Papa的朋友圈裏共有N 個人,給定一些這些人之間的喜歡關系,請你算出有多少個人可以當網紅。
輸入格式:
第一行:兩個用空格分開的整數:N和M
第二行到第M + 1行:每行兩個用空格分開的整數:A和B,表示A喜歡B
輸出格式:
第一行:單獨一個整數,表示朋友圈網紅的數量
輸入樣例:
3 3
1 2
2 1
2 3
輸出樣例:
1
說明
只有 3 號可以做網紅
【數據範圍】
10%的數據N<=20, M<=50
30%的數據N<=1000,M<=20000
70%的數據N<=5000,M<=50000
100%的數據N<=10000,M<=50000
雖然是道Tarjan裸題,但沒有學長指導確實自己做不出來
解析:
這道題我們用一個雙端隊列(vctor)來儲存A 喜歡 B,相當於建一條 A 指向 B 的單向邊
如圖
本來的關系應是這樣:
Tarjan後:
我們用一個 degree[] 儲存出口,在兩點不為強聯通分量時才存在出口,因此我們把出口的degree保持為 0,其余則改變為true
講道理出口有且僅有一個
如果存在兩個出口,那答案一定為0 —— 一定有兩人互不喜歡,就不滿足條件啦
MY:
#include<stdio.h> #include<algorithm> #include<stack> #include<vector> using namespace std; const int MX=10001; int n,m,k,cnt,dfn[MX],low[MX],belong[MX],degree[MX]; bool vis[MX]; stack<int> stk; vector<int> mp[MX]; void Tarjan(int x) { dfn[x]=low[x]=++k; vis[x]=1; stk.push(x); for(int j=0;j<mp[x].size();++j) { int next=mp[x][j]; if(!dfn[next]) { Tarjan(next); low[x]=min(low[x],low[next]); } else { low[x]=min(low[x],dfn[next]); } } if(dfn[x] == low[x]) { int top; cnt++; do { top=stk.top(); stk.pop(); belong[top]=cnt; }while(top!=x); } } void sol() { int ans=0,sum=0,index; for(int i=1;i<=n;++i) { for(int j=0;j<mp[i].size();++j) { if(belong[i] != belong[mp[i][j]]) degree[belong[i]]++; } } for(int i=1;i<=cnt;++i) { if(!degree[i]) sum++,index=i; } if(sum>1) { printf("0"); } else { for(int i=1;i<=n;++i) { if(belong[i] == index) { ans++; } } printf("%d",ans); } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) { int a,b; scanf("%d%d",&a,&b); mp[a].push_back(b); } for(int i=1;i<=n;++i) { if(!dfn[i]) Tarjan(i); } sol(); return 0; }
學長滴:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<stdlib.h> #include<vector> #include<stack> using namespace std; #define N 10005 stack<int> sta; vector<int> mp[N]; int dfn[N],low[N],vis[N],num[N],degree[N]; int n,m,cnt,id,ans; void init(){ cnt=0; id=0; ans=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num)); memset(degree,0,sizeof(degree)); while(!sta.empty()) sta.pop(); for(int i=1;i<=n;i++) mp[i].clear(); } void tarjan(int x){ dfn[x]=low[x]=++id; sta.push(x); vis[x]=1; for(int i=0;i<mp[x].size();i++){ int t=mp[x][i]; if(!dfn[t]) { tarjan(t); low[x]=min(low[x],low[t]); } else if(vis[t]) low[x]=min(low[x],dfn[t]); } if(dfn[x]==low[x]){ int tp; cnt++; do{ tp=sta.top(); vis[tp]=0; num[tp]=cnt; sta.pop(); }while(tp!=x); } } void solve(){ int sum=0,index; for(int i=1;i<=n;i++){ for(int j=0;j<mp[i].size();j++){ if(num[i]!=num[mp[i][j]]) degree[num[i]]++; } } for(int i=1;i<=cnt;i++){ if(!degree[i]) sum++,index=i; } if(sum>1) cout<<"0"<<endl; else { for(int i=1;i<=n;i++) if(num[i]==index) ans++; cout<<ans<<endl; } } int main(){ while(cin>>n>>m){ init(); for(int i=0;i<m;i++){ int a,b; cin>>a>>b; mp[a].push_back(b); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); solve(); } } /* 3 4 1 2 2 1 2 3 3 2 */
Papa的朋友圈(原POJ 2186)Tarjan