luogu_4017【题解】最大食物链计数(拓扑排序)

题目:https://www.luogu.org/problemnew/show/P4017

由于这个题有严格的偏序关系(应该严格吧)。明显就可以想到拓扑排序。

用吃与被吃建图。同时记录出度与入度。

求拓扑排序的同时。如果谁的出度为 0 。则证明这条链到头。ans++。

最后输出答案。

代码如下:

这是邻接表存图的,速度比较快。

#include<bits/stdc++.h>
#define sc(x) scanf("%d",&x)
using namespace std;
const int mod=80112002;
struct edge{
    int from,to,nxt;
}t[5000005];
int n,m,du[5005],chu[5005],f[5005],ans,head[5005];
queue<int> q;
inline void topo()
{
    for(int i=1;i<=n;i++)
        if(du[i]==0) q.push(i),f[i]=1;
    while(!q.empty()){
        int now=q.front();
        q.pop();
        for(int i=head[now];i;i=t[i].nxt){
            int tt=t[i].to;
            f[tt]+=f[now];
            f[tt]%=mod;
            du[tt]--;
            if(du[tt]==0){
                if(chu[tt]==0){
                    ans+=f[tt];
                    ans%=mod;
                }
                q.push(tt);
            }
        }
    }
}
int main()
{
    sc(n),sc(m);
    int tot=0;
    while(m--){
        int a,b;
        sc(a),sc(b);
        t[++tot].from=a;t[tot].to=b;t[tot].nxt=head[a];
        head[a]=tot;
        du[b]++;chu[a]++;
    }
    topo();
    cout<<ans<<endl;
    // system("pause");
    return 0;
}

然而最一开始我写的是vector的,感觉写的比较短,不用管那么多。

代码如下:

#include<bits/stdc++.h>
#define sc(x) scanf("%d",&x)
using namespace std;
const int mod=80112002;
struct edge{
    int from,to;
    edge() {}
    edge(int _from,int _to): from(_from),to(_to) {}
};
vector<edge> g[5000005];
int n,m,du[5005],chu[5005],f[5005],ans;
queue<int> q;
inline void topo()
{
    for(int i=1;i<=n;i++)
        if(du[i]==0) q.push(i),f[i]=1;
    while(!q.empty()){
        int now=q.front();
        q.pop();
        for(vector<edge>::iterator it=g[now].begin();it!=g[now].end();it++){
            int t=it->to;
            f[t]+=f[now];
            f[t]%=mod;
            du[t]--;
            if(du[t]==0){
                if(chu[t]==0){
                    ans+=f[t];
                    ans%=mod;
                }
                q.push(t);
            }
        }
    }
}
int main()
{
    sc(n),sc(m);
    while(m--){
        int a,b;
        sc(a),sc(b);
        g[a].push_back(edge(a,b));
        du[b]++;chu[a]++;
    }
    topo();
    cout<<ans<<endl;
    // system("pause");
    return 0;
}

这个时空比较爆炸。

但是感觉还是挺好写的(滑稽)。

原文地址:https://www.cnblogs.com/ChrisKKK/p/10960432.html