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

因为K只有50,所以想到用dp[ cr ][ j ]表示在点cr、比最短路多走了 j 的方案数。(看了TJ才知道)

因为不是DAG,所以没有拓扑序,就用记忆化搜索就好了。

判0环可以用bool数组,而且是栈的样子,表示从自己出发又一模一样地走回来就说明有0环。

0环还要在一条合法路径上才行。判断是dis[cr]+k+dit[cr]<=dis[n]+K。(dit是从n到各点的最短路)还可以用它剪枝。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const int N=1e5+,M=2e5+,S=,INF=0x3f3f3f3f;
int T,n,m,K,mod,hd[N],thd[N],xnt,tnt,dis[N],dit[N],f[N][S],ans;
bool vis[N],flag,gx[N][S];
struct Ed{
int nxt,to,w;
Ed(int n=,int t=,int w=):nxt(n),to(t),w(w) {}
}ed[M],ted[M];
int rdn()
{
int ret=;char ch=getchar();
while(ch>''||ch<'')ch=getchar();
while(ch>=''&&ch<='')(ret*=)+=ch-'',ch=getchar();
return ret;
}
priority_queue<pair<int,int> >q;
void dj()
{
memset(dis,0x3f,sizeof dis);dis[]=;
memset(vis,,sizeof vis);
q.push(make_pair(-dis[],));
while(q.size())
{
int k=q.top().second;q.pop();
while(q.size()&&vis[k])k=q.top().second,q.pop();
if(vis[k])break;vis[k]=;
for(int i=hd[k],v;i;i=ed[i].nxt)
if(dis[v=ed[i].to]>dis[k]+ed[i].w)
dis[v]=dis[k]+ed[i].w,q.push(make_pair(-dis[v],v));
}
memset(dit,0x3f,sizeof dit);dit[n]=;
memset(vis,,sizeof vis);
q.push(make_pair(-dit[n],n));
while(q.size())
{
int k=q.top().second;q.pop();
while(q.size()&&vis[k])k=q.top().second,q.pop();
if(vis[k])break;vis[k]=;
for(int i=thd[k],v;i;i=ted[i].nxt)
if(dit[v=ted[i].to]>dit[k]+ted[i].w)
dit[v]=dit[k]+ted[i].w,q.push(make_pair(-dit[v],v));
}
}
int dfs(int cr,int k)
{
if(gx[cr][k]){flag=;return -;}
if(f[cr][k])return f[cr][k];
if(cr==n)f[cr][k]=;//别return f[cr]=1,万一在终点连了一个0环
gx[cr][k]=;
for(int i=hd[cr],v;i;i=ed[i].nxt)
{
int w=dis[cr]+k+ed[i].w-dis[v=ed[i].to];
if(w>K||(ll)dis[v]+w+dit[v]>dis[n]+K)continue;
(f[cr][k]+=dfs(v,w))%=mod;
if(flag)return -;
}
gx[cr][k]=;//!
return f[cr][k];
}
int main()
{
T=rdn();
while(T--)
{
memset(hd,,sizeof hd);xnt=;
memset(thd,,sizeof thd);tnt=;
n=rdn();m=rdn();K=rdn();mod=rdn();
int x,y,z;
for(int i=;i<=m;i++)
{
x=rdn();y=rdn();z=rdn();
ed[++xnt]=Ed(hd[x],y,z);hd[x]=xnt;
ted[++tnt]=Ed(thd[y],x,z);thd[y]=tnt;
}
dj();
memset(f,,sizeof f);memset(gx,,sizeof gx);
flag=;ans=dfs(,);
if(flag)ans=-;
printf("%d\n",ans);
}
return ;
}

最新文章

  1. IGS_学习笔记01_Integrated SOA Gateway介绍(案例)
  2. Looksery Cup 2015 H. Degenerate Matrix 数学
  3. js、jquery、动态添加option项
  4. 向php文件中添加php.ini文件
  5. Div+Css的初步运用
  6. While installing plugin in eclipse luna, “Unable to acquire PluginConverter service” and “No repository found” errors appear in logs
  7. C/C++中的隐式类型转换
  8. JConsole 连接配置
  9. JS 混淆加密
  10. JDBC的基本用法
  11. Storm实践
  12. java JDK源码解析
  13. RedisHelper帮助类
  14. Multi-Projector Based Display Code ---- ModelViewer
  15. spark优化整理
  16. vue-cli之打包多入口配置
  17. js多维数组转一维数组
  18. eclipse-在编译项目时js特别慢的问题
  19. InnoDB Lock
  20. LINQ(数据库操作增、删、改及并发管理)

热门文章

  1. 使用 Vue.js 和 Chart.js 制作绚丽多彩的图表
  2. 安装office2019
  3. &lt;每日一题&gt;题目28:简单的python练习题(51-60)
  4. js (function(){}()),(function(){})(),$(function(){});之间的区别
  5. Leetcode322. Coin Change零钱兑换
  6. 【HAOI2015】树上染色—树形dp
  7. 巧用 position:absolute
  8. vue 路由(二级)配置及详细步骤
  9. springmvc 串口读写 基于win7使用txrx netbeans jdk1.8 maven的
  10. Eureka Instance实例信息配置