[Luogu] 逛公园

Posted xayata

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Luogu] 逛公园相关的知识,希望对你有一定的参考价值。

https://www.luogu.org/problemnew/show/P3953

https://www.zybuluo.com/wsndy-xx/note/1134388

 

 

#include<cstdio>
#include<cstring>
#include<cctype>

using namespace std;
const int N=1e5+1,K=51;

int n,m,k,p,tot,ans=0;
int first[N],next[N<<1],en[N<<1],w[N<<1];
int first1[N*K],next1[N*K<<1],en1[N*K<<1],d[N*K];
int q[N<<6],dis[N],dis1[N],u[N<<1],v[N<<1],t[N<<1],f[N*K];
bool bz[N];

inline int read() {
    int X=0,w=1;
    char ch=0;
    while(!isdigit(ch)) {
        if(ch==\'-\') w=-1;
        ch=getchar();
    }
    while(isdigit(ch)) X=(X<<3)+(X<<1)+ch-\'0\',ch=getchar();
    return X*w;
}

inline void insert(int x,int y,int z) {
    next[++tot]=first[x];
    first[x]=tot;
    en[tot]=y;
    w[tot]=z;
}

inline void insert1(int x,int y) {
    next1[++tot]=first1[x];
    first1[x]=tot;
    en1[tot]=y;
    d[y]++;
}

inline int get(int x,int y) {
    return (x-1)*(k+1)+y+1;
}

int main() {
    int T=read();
    while(T--) {
        n=read(),m=read(),k=read(),p=read();
        memset(first,tot=0,sizeof(first));
        for(int i=1; i<=m; i++) {
            u[i]=read(),v[i]=read(),t[i]=read();
            insert(u[i],v[i],t[i]);
        }
        memset(dis,60,sizeof(dis));
        int l=dis[1]=0,r=q[1]=1;
        while(l<r) {
            int x=q[++l];
            bz[x]=false;
            for(int i=first[x]; i; i=next[i])
                if(dis[x]+w[i]<dis[en[i]]) {
                    dis[en[i]]=dis[x]+w[i];
                    if(!bz[en[i]]) bz[q[++r]=en[i]]=true;
                }
        }
        memset(first,tot=0,sizeof(first));
        for(int i=1; i<=m; i++) insert(v[i],u[i],t[i]);
        memset(dis1,60,sizeof(dis1));
        l=dis1[q[r=1]=n]=0;
        while(l<r) {
            int x=q[++l];
            bz[x]=false;
            for(int i=first[x]; i; i=next[i])
                if(dis1[x]+w[i]<dis1[en[i]]) {
                    dis1[en[i]]=dis1[x]+w[i];
                    if(!bz[en[i]]) bz[q[++r]=en[i]]=true;
                }
        }
        memset(first1,tot=0,sizeof(first1));
        memset(d,0,sizeof(d));
        for(int i=1; i<=m; i++) {
            int x=get(u[i],0),y=get(v[i],dis[u[i]]+t[i]-dis[v[i]]);
            for(int j=dis[u[i]]; j+t[i]+dis1[v[i]]<=dis[n]+k; j++,x++,y++) insert1(x,y);
        }
        int num=(k+1)*n,sum=0;
        l=r=ans=0;
        memset(f,0,sizeof(f));
        for(int i=1; i<=num; i++)
            if(!d[i]) q[++r]=i;
        f[1]=1;
        while(l<r) {
            int x=q[++l];
            sum++;
            for(int i=first1[x]; i; i=next1[i]) {
                if(!--d[en1[i]]) q[++r]=en1[i];
                f[en1[i]]+=f[x];
                f[en1[i]]=f[en1[i]]>p?f[en1[i]]-p:f[en1[i]];
            }
        }
        if(sum<num) printf("-1\\n");
        else {
            for(int i=0; i<=k; i++) ans=(ans+f[get(n,i)])%p;
            printf("%d\\n",ans);
        }
    }
    return 0;
}

 

以上是关于[Luogu] 逛公园的主要内容,如果未能解决你的问题,请参考以下文章

[Luogu] 逛公园

[luogu P3953] [noip2017 d1t3] 逛公园

Luogu P3953NOIP2017逛公园最短路+拓扑排序+动态规划

luogu 3953 逛公园

luogu3563 逛公园

luogu P4513ybtoj线段树课堂过关例题3小白逛公园