P4017 最大食物鏈計數 (拓撲排序)
看到拓撲排序感覺非常遙遠的復雜,不喜歡圖。看了拓撲排序的原理,很像廣搜。
以本題樣例為例:

了解一下 出度 和 入度
5的出度為3 入度為 0 ,3的出度為2 入度為2……
for循環 找到禿頭 5 入隊列, 然后給跟他有聯系的所有點一一剃頭,看誰再禿,禿了入隊列,再對繼往開來的禿子進行操作。
#include<cstdio> #include<iostream> #include<queue> using namespace std; int n,m,ru[5050],chu[5050],f[5050],a,t,ans,b,s[5050][5050]; //ru[]是入度,chu[]是出度(后面判斷是否為尾巴用的),f[i]代表到i點多少條路徑, s[][]鄰接矩陣存儲兩點之間是否有聯系。 queue<int> q; int main() { scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); ru[a]++; chu[b]++; s[b][a]=1; } for(int i=1;i<=n;i++) { if(ru[i]==0)//尋找先天的禿子 { q.push(i); f[i]=1; } } while(true) { if(q.empty())break;//禿子隊列沒了,就結束了。 t=q.front();//找出隊列前端的禿子,暫存到t里。 q.pop();// 沒用了的禿子消失吧。 for(int i=1;i<=n;i++) { if(s[t][i]==1)//找到和禿子有聯系的家伙,間斷它們之間的煩惱絲 { f[i]+=f[t];//凡是和它有聯系的都要把方案+上它(遞推),不懂這一點的遞推做一做過河卒 f[i]=f[i]%80112002; ru[i]--;//剪掉入度 if(ru[i]==0)//看看禿了沒有 { if(chu[i]==0)//看看到尾巴了嗎?如果沒有出度了,說明沒有了后續,等著干啥,統計一下吧。 { ans+=f[i];//因為可能有多個尾巴,所以這里要用+=。如果沒有這個,就是單尾巴。 ans=ans%80112002; continue; } q.push(i);//剪禿了,入隊列吧。 } } else { continue; } } } cout<<ans; return 0; }

浙公網安備 33010602011771號