图解Topo拓扑排序 例题洛谷P4017 最大食物链计数

适用条件:无环图

输出结果:使得每个节点,以它为终点的起点节点排都在其前面

作用:递推保证前面的节点都已经被使用过

实现方法:从没有入边的节点开始,输出并从其他节点中删去自己,重复此步骤直到所有节点都被输出

图解:

算法实现: 

1.记录节点的入边的个数

2.将入边个数为0的加入队列

3.从队列中取点,输出并删去该点,将以它为起点的节点的入边都减1,如果减为0就加入队列。

4.重复3步骤直到所有数均被输出

 例题:洛谷P4017 最大食物链计数

思路:

到某个生物的可能食物链数量为它所有可吃的生物的可能食物链数量之和,但再此之前,那些可吃的生物的可能食物链数量必须已经被算出来,这时结合我们的拓扑排序就能解决这个问题

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 5e3 + 10,MAXM = 5e5 + 10,MOD = 80112002;
int ptop = 1;
ll sum = 0,a[MAXN];
bool use[MAXN];
struct link{
	int p;
	link* nex;
}p[MAXM],q[MAXM];
link* head[MAXN],*qhead[MAXN];
void add(int x,int y)
{
	p[ptop].nex = head[x];
	p[ptop].p = y;
	head[x] = &p[ptop];
	q[ptop].nex = qhead[y];
	q[ptop].p = x;
	qhead[y] = &q[ptop]; 
	ptop++;
}
int dad[MAXN];
int son[MAXN];
queue<int> qu;
void adddad(int x)
{
	link* pp = head[x];
	while(pp != NULL)
	{
		int y = pp -> p;
		a[y] += a[x];
		a[y] %= MOD;
		son[y]--;
		if(son[y] == 0)
		qu.push(y);
		pp = pp -> nex;
	}
}
int main()
{
	int n,m;cin >> n >> m;
	for(int i = 1;i <= m;i++)
	{
		int x,y;scanf("%d %d",&x,&y);
		add(x,y);
		dad[x]++;
		son[y]++;
	}
	for(int i = 1;i <= n;i++)
	{
		if(son[i] == 0)
		{
			a[i] = 1;
			qu.push(i);
		}
		
	}
	while(!qu.empty())
	{
		int x = qu.front();qu.pop();
		adddad(x);
		if(dad[x] == 0)
		sum += a[x],sum %= MOD;
	}
	cout << sum;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值