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

时间: 2024-11-05 22:32:45

luogu_4017【题解】最大食物链计数(拓扑排序)的相关文章

20151230训练题解(最短路+拓扑排序)

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=103223#problem/B 这道题用经典的dijsktra算法,大概思路就是用dist[x]存储x到已经确定集合的最短路,n次循环到这个这个最小值,然后更新其他点到新集合的最短路即对应的dist[] 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <al

HDU 5438 拓扑排序+DFS

Ponds Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 3234    Accepted Submission(s): 997 Problem Description Betty owns a lot of ponds, some of them are connected with other ponds by pipes, a

hdu 5438 Ponds 拓扑排序

Ponds Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1001&cid=621 Description Betty owns a lot of ponds, some of them are connected with other ponds by pipes, and there will not be more than one

Legal or Not(拓扑排序判环)

http://acm.hdu.edu.cn/showproblem.php?pid=3342 Legal or Not Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5788    Accepted Submission(s): 2678 Problem Description ACM-DIY is a large QQ group w

UVa 10305 - Ordering Tasks 拓扑排序题解

Topological Sort题解.本题是简单的入门题目. Topological Sort的思想很简单,就是按没有入度的点,先输出,然后删除这个点的出度.然后输出下一组没有入度的点. 如何实现也是很简单的: 这里使用邻接表,建图的时候反过来建图,建立一个入度邻接表. 然后使用一个vis数组,记录访问过的节点,也可以根据这个信息知道哪些是已经输出的点,这个时候这些点的入度可以不算为当前入度了. #include <stdio.h> #include <vector> using

ZJU 1346 Comparing Your Heroes 状态压缩DP 拓扑排序的计数

做多校的时候遇见一个求拓扑排序数量的题,就顺便来写了一下. 题意: 你有个朋友是KOF的狂热粉丝,他有一个对其中英雄的强弱比较,让你根据这些比较关系来给这些英雄排名.问一共有多少种排名方式. 思路: 用dp[S]记录当前状态的数量. S表示拓扑排序中当前阶段已经被排序的点的集合.然后就可以枚举当前排序的点,转移的条件是这个点的所有前驱都被排序,而且这个点没被排序.然后转移就好了,最终状态就是所有点都完成排序. 代码: 1 #include <iostream> 2 #include <c

HDU 4917 Permutation 拓扑排序的计数

题意: 一个有n个数的排列,给你一些位置上数字的大小关系.求合法的排列有多少种. 思路: 数字的大小关系可以看做是一条有向边,这样以每个位置当点,就可以把整个排列当做一张有向图.而且题目保证有解,所以只一张有向无环图.这样子,我们就可以把排列计数的问题转化为一个图的拓扑排序计数问题. 拓扑排序的做法可以参见ZJU1346 . 因为题目中点的数量比较多,所以无法直接用状压DP. 但是题目中的边数较少,所以不是联通的,而一个连通块的点不超过21个,而且不同连通块之间可以看做相互独立的.所以我们可以对

暑假集训之专题----拓扑排序题解

第一单: Problem A Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 26   Accepted Submission(s) : 5 Problem Description ACM-DIY is a large QQ group where many excellent acmers get together. It is so h

最大食物链计数 题解

文字讲解 题目分析: 首先 ,要知道这道拓扑排序题目的性质. 食物链中的生物 -- 节点 生物之间的关系 -- 有向边 为了方便描述,我们 将 最左端是不会捕食其他生物的生产者 叫做 最佳生产者 将 最右端是不会被其他生物捕食的消费者 叫做 最佳消费者 数据中不会出现环 那么,"最大食物链"就是左端是 最佳生产者 ,右端是 最佳消费者 思路引导 易得,想要找到一条 最大食物链 ,则起始点入度要为0,终点出度要为0.于是有: 既要记录入度,还要记录出度! 现在的问题就是,如何找到所有的最