NOIP2017 逛公园 (Dijkstra)


luogu P3953 逛公园##

  Time Limit: 10 Sec
  Memory Limit: 128 MB

Description###

   策策同学特别喜欢逛公园。公园可以看成一张\(N\)个点\(M\)条边构成的有向图,且没有 自环和重边。其中1号点是公园的入口,\(N\)号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间。
   策策每天都会去逛公园,他总是从1号点进去,从\(N\)号点出来。
   策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间。如果1号点 到\(N\)号点的最短路长为\(d\),那么策策只会喜欢长度不超过\(d + K\)的路线。
   策策同学想知道总共有多少条满足条件的路线,你能帮帮它吗?
   为避免输出过大,答案对\(P\)取模。
   如果有无穷多条合法的路线,请输出\(−1\)
 

Input###

   第一行包含一个整数 TT, 代表数据组数。
   接下来TT组数据,对于每组数据: 第一行包含四个整数 N,M,K,PN,M,K,P,每两个整数之间用一个空格隔开。
   接下来MM行,每行三个整数\(a_i,b_i,c_i\) ,代表编号为\(a_i,b_i\)的点之间有一条权值为 \(c_i\)的有向边,每两个整数之间用一个空格隔开。
 

Output###

   输出文件包含 \(T\) 行,每行一个整数代表答案。
 

Sample Input###

   2
   5 7 2 10
   1 2 1
   2 4 0
   4 5 2
   2 3 2
   3 4 1
   3 5 2
   1 5 3
   2 2 0 10
   1 2 0
   2 1 0
 

Sample Output###

  3
  -1

HINT

题目地址:luogu P3953 逛公园

题目大意: 题目很简洁了:)

题解:

  只是因为 Dijkstra 写挂了来粘一发
  **刷历年noip ing **


AC代码

// luogu-judger-enable-o2
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define pa pair<int,int>
using namespace std;
const int N=1e5+5,inf=1e9;
int n,m,K,Mod;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct edge{
    int to,val,next;
}e[N+N];
int cnt_edge,last[N];
inline void add_edge(int u,int v,int w){
    e[++cnt_edge]=(edge){v,w,last[u]};last[u]=cnt_edge;
}
inline int mo(int x){
    if(x>=Mod)return x-Mod;
    return x;
}
priority_queue<pa,vector<pa>,greater<pa> > q;
int dis[N];
bool vis[N];
inline void dijkstra(){
    for(int i=1;i<=n;i++)dis[i]=inf;
    memset(vis,0,sizeof(vis));
    dis[1]=0;
    q.push(make_pair(0,1));
    while(!q.empty()){
        int u=q.top().second;q.pop();
        vis[u]=1;                                            //特别
        for(int i=last[u];i;i=e[i].next){
            int v=e[i].to;
            if(vis[v])continue;
            if(dis[v]>dis[u]+e[i].val){
                dis[v]=dis[u]+e[i].val;
                q.push(make_pair(dis[v],v));
            }
        }
    }
}
int f[N][55];
bool ins[N][55];
int dfs(int u,int d){
    int delta=d-dis[u];
    if(ins[u][delta])return -1;
    if(f[u][delta]!=-1)return f[u][delta];
    ins[u][delta]=1;
    if(u==n)f[u][delta]=1;
    else f[u][delta]=0;
    int res=0;
    for(int i=last[u];i;i=e[i].next){
        int v=e[i].to;
        if(d+e[i].val<=dis[v]+K){
            int val=dfs(v,d+e[i].val);
            if(val==-1)return f[u][delta]=-1;
            res=mo(res+val);
        }
    }
    ins[u][delta]=0;
    f[u][delta]=(f[u][delta]+res);
    return f[u][delta];
}
int main(){
    int Q=read();
    while(Q--){
        n=read(),m=read(),K=read(),Mod=read();
        cnt_edge=0;
        memset(last,0,sizeof(last));
        for(int i=1;i<=m;i++){
            int u=read(),v=read(),w=read();
            add_edge(u,v,w);
        }
        dijkstra();
        memset(ins,0,sizeof(ins));
        memset(f,-1,sizeof(f));
        printf("%d\n",dfs(1,0));
    }
    return 0;
}


  作者:skl_win
  出处:https://www.cnblogs.com/shaokele/
  本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

posted @ 2018-10-16 17:56  skl_win  阅读(217)  评论(0编辑  收藏  举报
Live2D