【动态规划1】动态规划的引入 P4017 最大食物链计数 拓扑排序
该题是有向图。
样例数据模拟如下所示,可结合AC代码进行阅读:
状态转移方程:
f[v]=(f[v]+f[u])%mod;
该题难点在于:存在多个 最左端,存在多个 最右端.
故应输出多个 最右端 的和。
AC代码如下:
#include <bits/stdc++.h>
#define mod 80112002
#define maxn 5010
#define maxm 500010
int n,m,head[maxn],tot,rd[maxn],cd[maxn],f[maxn];//rd[]入度,cd[]出度
int q[maxn],h,t;
struct node{
int to,next;
}e[maxm];
void add_edge(int u,int v){//邻接表
tot++,e[tot].to=v,e[tot].next=head[u],head[u]=tot;
}
void topsort(){//拓扑排序
int u,v,b;
h=t=1;
for(u=1;u<=n;u++)//存在多个最左端
if(!rd[u])f[u]=1,q[t]=u,t++;
while(h<t){
u=q[h];
for(b=head[u];b;b=e[b].next){
v=e[b].to;
rd[v]--;
f[v]=(f[v]+f[u])%mod;
if(!rd[v])q[t]=v,t++;
}
h++;
}
}
int main(){
int i,u,v,b,sum=0;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++){
scanf("%d%d",&u,&v);
add_edge(u,v);
rd[v]++,cd[u]++;
}
topsort();
for(i=1;i<=n;i++)//存在多个最右端
if(!cd[i])sum=(sum+f[i])%mod;
printf("%d\n",sum);
return 0;
}