洛谷题单指南-图的基本应用-P4017 最大食物链计数

原题链接:https://www.luogu.com.cn/problem/P4017

题意解读:食物链的顶端不会被其他生物吃,在图结构中设定为入度是0,食物链的底端不会吃其他生物,在图结构中设定为出度是0,此题就是要计算所有入度是0的点到所有出度是0的点一共有多条路径。

解题思路:

首先,来模拟样例,样例数据形成的图如下:

在此图中,食物链的顶端是1,食物链的底端是5,要求1->5的所有路径数,其实就是求有多少条路可以到达5

设数组l[N]为顶端到每个节点的路径条数

节点5可以从2、3、4过来,因此l[5] = l[2] + l[3] + l[4]

节点2可以从1过来,l[2] = l[1],节点1的路径数就是1,l[1] = 1,所以l[2] = 1

节点3可以从1、2过来,l[3] = l[2] + l[1] = 1 + 1 = 2

节点4可以从3过来,l[4] = l[3] = 2

所以l[5] = 1 + 2 + 2 = 5

以上过程,其实本质上,就是计算到每个节点的路径条数。

在拓扑排序的过程中,会先搜索完某个节点所有的前置节点,这个过程就可以计算到这个节点的路径数,等于到所有前置节点路径数之和,

到所有顶端节点(入度为0)的路径数都初始化为1即可,

另外,注意底端节点可能有多个,要把到所有出度为0的节点路径数加起来。

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 5005;
const int MOD = 80112002;

vector<int> g[N];
queue<int> q;
int in[N], out[N]; //入度、出度
int l[N]; //到每个节点的路径条数
int n, m, a, b;
int ans;

void bfs()
{
    for(int i = 1; i <= n; i++)
    {
        if(in[i] == 0)
        {
            q.push(i);
            l[i] = 1; //到入度为0的节点的路径数是1
        }
    }
    while(q.size())
    {
        int u = q.front(); q.pop();
        for(int i = 0; i < g[u].size(); i++)
        {
            int v = g[u][i];
            if(--in[v] == 0) q.push(v);
            l[v] = (l[v] + l[u]) % MOD; //到v的路径条数就是到所有前置节点的路径条数之和
        }
    }
}

int main()
{
    cin >> n >> m;
    while(m--)
    {
        cin >> a >> b;
        g[b].push_back(a);
        in[a]++; //记录入度
        out[b]++; //记录出度
    }
    bfs();
    for(int i = 1; i <= n; i++)
    {
        if(out[i] == 0)
        {
            ans = (ans + l[i]) % MOD; //计算到所有出度为0的节点的路径数之和
        }
    }
    cout << ans;

    return 0;
}

 

posted @ 2024-03-28 13:47  五月江城  阅读(40)  评论(0编辑  收藏  举报