• luogu 3953 逛公园


    noip2017 D1T3 逛公园 某zz选手看到数据范围直接就最短路计数了,结果写错了爆零

    题目大意:

    N个点M条边构成的有向图,且没有自环和重边。其中1号点是起点,N号点是公园的终点,每条边有一个非负权值, 代表经过这条边所要花的时间

    如果1号点到N号点的最短路长为d,那么策策只选择长度不超过d + K的路线

    求总共有多少条满足条件的路线

    为避免输出过大,答案对P取模。

    如果有无穷多条合法的路线,请输出−1

    思路:

    首先需要求出最短路用spfa

    然后我们dfs的时候dp

    具体见注释

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #define inf 2139062143
    10 #define ll long long
    11 #define MAXN 100100
    12 using namespace std;
    13 inline int read()
    14 {
    15     int x=0,f=1;char ch=getchar();
    16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    18     return x*f;
    19 }
    20 int T,n,m,k,MOD;
    21 int cnt,nxt[MAXN*2],fst[MAXN],to[MAXN*2],val[MAXN*2];
    22 int Cnt,Nxt[MAXN*2],Fst[MAXN],To[MAXN*2],Val[MAXN*2];
    23 int dis[MAXN],dp[MAXN][55];
    24 bool vis[MAXN],jdg[MAXN][55],f;
    25 void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
    26 void Add(int u,int v,int w) {Nxt[++Cnt]=Fst[u],Fst[u]=Cnt,To[Cnt]=v,Val[Cnt]=w;}
    27 void spfa()
    28 {
    29     memset(dis,127,sizeof(dis));
    30     queue <int> q;
    31     dis[1]=0,vis[1]=1;q.push(1);
    32     while(!q.empty())
    33     {
    34         int k=q.front();
    35         q.pop();vis[k]=0;
    36         for(int i=fst[k];i;i=nxt[i])
    37             if(dis[k]+val[i]<dis[to[i]]) {dis[to[i]]=dis[k]+val[i];if(!vis[to[i]]){vis[to[i]]=1;q.push(to[i]);}}
    38     }
    39 }
    40 int dfs(int x,int ext)//表示走到x节点刚好多走了ext dfs的时候按照反向边走 
    41 {
    42     if(dp[x][ext]!=-1) return dp[x][ext];
    43     jdg[x][ext]=1,dp[x][ext]=0;//jdg用来判零环 (如果一个点相同的ext在dp还未被确定的情况下被访问了两遍,说明有零环)
    44     for(int i=Fst[x];i;i=Nxt[i])
    45     {
    46         if(dis[x]-dis[To[i]]+ext-Val[i]<0) continue;//这么长的一大串表示按这条边走的ext <0说明不能按这条边走 
    47         if(jdg[To[i]][dis[x]-dis[To[i]]+ext-Val[i]]) f=1;//有零环 
    48         (dp[x][ext]+=dfs(To[i],dis[x]-dis[To[i]]+ext-Val[i]))%=MOD;//接着dfs 
    49     }
    50     jdg[x][ext]=0;
    51     return dp[x][ext];
    52 }
    53 int main()
    54 {
    55     T=read();
    56     int a,b,c,ans=0;
    57     while(T--)
    58     {
    59         memset(nxt,0,sizeof(nxt));
    60         memset(Nxt,0,sizeof(Nxt));
    61         memset(Fst,0,sizeof(Fst));
    62         memset(fst,0,sizeof(fst));
    63         memset(jdg,0,sizeof(jdg));
    64         memset(vis,0,sizeof(vis));
    65         memset(dp,0xff,sizeof(dp));//设为-1是因为在这个dp里 0也是一种合法的结果 
    66         n=read(),m=read(),k=read(),MOD=read(),cnt=Cnt=0;
    67         for(int i=1;i<=m;i++) {a=read(),b=read(),c=read();add(a,b,c);Add(b,a,c);}
    68         spfa();//处理出最短路 
    69         ans=f=0,dp[1][0]=1;
    70         for(int i=0;i<=k;i++) (ans+=dfs(n,i))%=MOD;//倒着dfs 在搜索的过程中能够非常巧妙地判断零环 
    71         dfs(n,k+1);//用来判断k==0时有零环的情况 
    72         if(f) puts("-1");
    73         else printf("%d
    ",ans);
    74     }
    75 }
    View Code
  • 相关阅读:
    在子线程中使用Toast
    时间戳与字符串的转换
    Notification小案例
    Android文件的读写操作
    SmartImageView-网络图片查看器
    JavaScript中判断对象类型的种种方法
    nodejs npm常用命令
    web前端安全机制问题全解析
    Gulp安装及配合组件构建前端开发一体化(转)
    gulp 实现 js、css,img 合并和压缩(转)
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/8000123.html
Copyright © 2020-2023  润新知