Live2D

[题解]洛谷P4017 最大食物链计数

一开始不知道toposort可以做,写了个记忆化搜索,结果T了qwq

然后一看题解,豁然开朗,本蒟蒻见识浅短,还不曾知道还有这种操作

设 f[i] 是以i结尾的最长链个数,那么 f[i]=∑f[k] (k有一条出边指向i)

然后统计出度为0的点i的f[i],累加就是ans

这一过程显然可以在toposort里VAN成

代码:

#include<cstdio>
#include<cstring> 
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN = 5001,MAXM = 500001,MOD = 80112002;
typedef long long ll;

inline int read(){
    int x=0,w=1;char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')w=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<3)+(x<<1)+c-'0';
        c=getchar();
    }
    return x*w;
}

int n,m,ans=0;
int first[MAXN];

struct edge{
    int v,next;
}e[MAXM];

int tot=0;
void insert(int u,int v){
    ++tot;e[tot].v=v;e[tot].next=first[u];first[u]=tot;
}

int f[MAXN],rd[MAXN],cd[MAXN];
queue<int> q;
void solve(){
    for(register int i=1;i<=n;i++)
        if(!rd[i]){
            q.push(i);f[i]=1;
        }
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=first[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            f[v]+=f[u];f[v]%=MOD;
            if(!--rd[v])q.push(v);
        }
    }
}

int main(){
    memset(first,-1,sizeof(first));
    n=read();m=read();
    for(register int i=1;i<=m;i++){
        int x=read(),y=read();
        rd[y]++;cd[x]++;
        insert(x,y);
    }
    solve();
    for(register int i=1;i<=n;i++)
        if(!cd[i]){
            ans+=f[i];ans%=MOD;
        }
    printf("%d",ans%MOD);
    return 0;
} 

 

posted @ 2019-02-17 20:38  SHGEEK  阅读(152)  评论(0编辑  收藏  举报