原題 比較經典吧 (洛谷上粘的) [HAOI2006]受歡迎的牛 題目描述 每頭奶牛都夢想成為牛棚里的明星。被所有奶牛喜歡的奶牛就是一頭明星奶牛。所有奶
牛都是自戀狂,每頭奶??偸窍矚g自己的。奶牛之間的“喜歡”是可以傳遞的——如果A喜
歡B,B喜歡C,那么A也喜歡C。牛欄里共有N 頭奶牛,給定一些奶牛之間的愛慕關系,請你
算出有多少頭奶??梢援斆餍恰?/p>
輸入輸出格式
輸入格式: ? 第一行:兩個用空格分開的整數:N和M
? 第二行到第M + 1行:每行兩個用空格分開的整數:A和B,表示A喜歡B
輸出格式: ? 第一行:單獨一個整數,表示明星奶牛的數量
輸入輸出樣例
輸入樣例#1: 3 3 1 2 2 1 2 3 輸出樣例#1: 1 說明
只有 3 號奶牛可以做明星
【數據范圍】
10%的數據N<=20, M<=50
30%的數據N<=1000,M<=20000
70%的數據N<=5000,M<=50000
100%的數據N<=10000,M<=50000
其實是一個強連通分量的基礎題,我是用的 tarjan 首先要 理解Tarjan的原理 并能掌握其代碼模板(我這沒講,去百度查); 然后在 Tarjan 深搜完后退棧時做個小記錄就行了,我感覺所謂縮點其實沒真縮(因為沒有建新圖嘛), 只是統計了一下每個點所屬的強連通分量,以及每個分量 所含點的數量,tarjan完了之后遍歷每個邊, 記了每個分量的出度(只有唯一一個出度為零的分量才能成明星),看是否只有一個滿足的分量,然 后得到答案(即那個分量所含的點數); 看代碼
#include<iostream>#include<cstdio>#include<cstring>using namespace std;int n,m;int top,stack[100010];bool instack[100010];// zhanint dfn[100010],low[100010],step;//tarjanint belong[100010],outd[100010],mem[100010],totq,popular,ans;//suo dianint cnt,last[100010];struct E{ int to,fro,next;}a[500010]; //lian shi qiang xiang xingvoid bud(int u,int v){ a[++cnt].to=v;a[cnt].fro=u;a[cnt].next=last[u];last[u]=cnt;} void tarjan(int x){ dfn[x]=low[x]=++step; stack[++top]=x;instack[x]=1; for(int i=last[x];i;i=a[i].next){ if(!dfn[a[i].to]){ tarjan(a[i].to); if(low[x]>low[a[i].to]) low[x]=low[a[i].to]; } else if(instack[a[i].to]&&low[x]>dfn[a[i].to]) low[x]=dfn[a[i].to]; } if(dfn[x]==low[x]){ totq++;int t; do{ t=stack[top]; instack[t]=0; belong[t]=totq; mem[totq]++; top--; }while(t!=x); }}int main(){ freopen("in.txt","r",stdin); scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) { int u,v; scanf("%d%d",&u,&v); bud(u,v); } for(int i=1;i<=n;++i){ if(!dfn[i]) tarjan(i); } for(int i=1;i<=m;++i) if(belong[a[i].fro]!=belong[a[i].to]) outd[belong[a[i].fro]]++; for(int i=1;i<=totq;++i){ if(outd[i]==0){ popular++; ans=i; } } if(popular==1)新聞熱點
疑難解答