暑假集訓Day13 食物鏈
阿新 • • 發佈:2020-07-05
題目大意
現在給你n個物種和m條能量流動關係,求其中的食物鏈條數。
物種的名稱為從1到n的編號。
m條能量流動關係形如
\(a_1 b_1\)
\(a_2 b_2\)
\(a_3 b_3\)
\(a_4 b_4\)
...
\(a_m b_m\)
其中\(a_i b_i\)表示能量從物種\(a_i\)流向物種\(b_i\) 。注意單獨的一種孤立生物不算一條食物鏈。
輸入格式
第一行兩個整數n和m,接下來m行每行兩個整數\(a_i b_i\)描述m條能量流動關係。
(保證輸入資料符合生物學特點,即不存在環,且不會有重複的能量流動關係出現)
輸出格式
一個整數,即食物網中的食物鏈條數。
樣例
樣例輸入
10 16
1 2
1 4
1 10
2 3
2 5
4 3
4 5
4 8
6 5
7 6
7 9
8 5
9 8
10 6
10 7
10 9
樣例輸出
9
演算法分析:
- 這是一個很裸的圖論的題了(考試爆零真的是我的原因了)
- 其實真的很裸沒啥可分析的………………
- 跑拓撲或者dfs都行
- 直接看程式碼吧
程式碼展示
#include<bits/stdc++.h> using namespace std; const int maxn = 1e6+10; int cnt,n,m; int head[maxn],rd[maxn],cd[maxn],dp[maxn]; struct edge{int to,next;}a[maxn]; void add(int x,int y){ a[++cnt].to = y; a[cnt].next = head[x]; head[x] = cnt; } queue<int> q; int main(){ scanf("%d%d",&n,&m); for(int i = 1;i <= m;++i){ int x,y;scanf("%d%d",&x,&y); rd[y]++;//入度 cd[x]++;//出度 add(x,y); } for(int i = 1;i <= n;++i){ if(!rd[i]){//沒有入度說明是根節點 q.push(i); if(cd[i] != 0)dp[i] = 1;//如果不是葉子節點 就將鏈數置為1 } } while(!q.empty()){ int x = q.front();//取出隊首 q.pop(); for(int i = head[x];i;i = a[i].next){//依次遍歷隊首每一個兒子 dp[a[i].to] += dp[x];//兒子的鏈數 += 父親的鏈數(自己想為啥吧 要不然就畫圖) rd[a[i].to] -= 1;//減去當前父親的入度 已經計算過了 方便再以這個兒子跑拓撲 if(rd[a[i].to] == 0){//類似於深搜 將沒有入度的點入隊 q.push(a[i].to); } } } int ans = 0; for(int i = 1;i <= n;++i)if(cd[i] == 0)ans += dp[i];//把各個葉子節點的權值加上 printf("%d",ans); return 0; }
考試的時候沒看懂樣例 鏈數沒數過來 呀咦惹
謝謝觀看
點個關注 >,<