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;
} 

 

posted @ 2020-06-17 09:56  爆零教練員  阅读(188)  评论(0编辑  收藏  举报