码迷,mamicode.com
首页 > 其他好文 > 详细

[Luogu] 逛公园

时间:2018-05-02 22:13:26      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:sum   first   com   namespace   ext1   false   new   图片   name   

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

技术分享图片

技术分享图片

技术分享图片

技术分享图片

 

 技术分享图片

技术分享图片

#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] 逛公园

标签:sum   first   com   namespace   ext1   false   new   图片   name   

原文地址:https://www.cnblogs.com/shandongs1/p/8982527.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!