题目: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 ;
}

洛谷3953 (NOIp2017) 逛公园——记忆化搜索+用栈判0环的更多相关文章

  1. NOIP 2017 逛公园 记忆化搜索 最短路 好题

    题目描述: 策策同学特别喜欢逛公园.公园可以看成一张N个点MM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间. ...

  2. 洛谷P1434滑雪题解及记忆化搜索的基本步骤

    题目 滑雪是一道dp及记忆化搜索的经典题目. 所谓记忆化搜索便是在搜索的过程中边记录边搜索的一个算法. 当下次搜到这里时,便直接使用. 而且记忆化搜索一定要满足无后效性,为什么呢,因为如果不满足无后效 ...

  3. 洛谷P1192 台阶问题【记忆化搜索】

    题目:https://www.luogu.org/problemnew/show/P1192 题意: 给定n和k,一个人一次可以迈1~k步,问走n步有多少种方案. 思路: 本来傻乎乎上来就递归,显然会 ...

  4. 洛谷P1040 加分二叉树【记忆化搜索】

    题目链接:https://www.luogu.org/problemnew/show/P1040 题意: 某一个二叉树的中序遍历是1~n,每个节点有一个分数(正整数). 二叉树的分数是左子树分数乘右子 ...

  5. 洛谷P3953 [NOIP2017]逛公园

    K<=50,感觉可以DP 先建反图求出从n到各个点的最短路,然后在正图上DP 设f[当前点][比最短路多走的距离]=方案数 转移显然是 $f[v][res]=\sum f[u][res+tmp] ...

  6. 洛谷 P1141【BFS】+记忆化搜索+染色

    题目链接:https://www.luogu.org/problemnew/show/P1141 题目描述 有一个仅由数字 0 与 1 组成的n×n 格迷宫.若你位于一格0上,那么你可以移动到相邻 4 ...

  7. 洛谷P3906 Hoof Paper, Scissor (记忆化搜索)

    这道题问的是石头剪刀布的的出题问题 首先不难看出这是个dp题 其次这道题的状态也很好确定,之前输赢与之后无关,确定三个状态:当前位置,当前手势,当前剩余次数,所以对于剪刀,要么出石头+1分用一次机会, ...

  8. 【洛谷1434 [SHOI2002]滑雪】记忆化搜索

    AC代码 #include <bits/stdc++.h> using namespace std; #define ms(a,b) memset(a,b,sizeof(a)) typed ...

  9. 【题解】洛谷P3953 [NOIP2017TG] 逛公园(记忆化搜索+SPFA)

    题目来源:洛谷P3953 思路 先用SPFA求一遍最短路 在求最短路的同时可以把所有点到终点的最短路求出来 dis数组 注意要反向SPFA  因为从起点开始可能会走到一些奇怪的路上导致时间负责度增加 ...

随机推荐

  1. java 调用区块链 发布和调用智能合约

    java连接区块链 很简单 ,调用智能合约要麻烦一些. 先说连接 区块链查询数据. 1 maven 项目导入 web3j 的依赖. <dependency> <groupId> ...

  2. hibernate离线条件查询设置or关系

    detachedCriteria.add(Restrictions.or(Restrictions.isNull(""), Restrictions.isNull("&q ...

  3. 【转载】unittest总结

    本文转载链接:http://www.cnblogs.com/yufeihlf/p/5707929.html unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执 ...

  4. 《DSP using MATLAB》Problem 8.28

    代码: %% ------------------------------------------------------------------------ %% Output Info about ...

  5. Activiti流程实例管理

    1.启动流程 在完成了流程定义部署后,就要启动流程实例了. /** * 1 启动流程 * 当流程到达一个节点时,会在act_ru_execution表中产生1条数据 * 如果当前节点是用户任务节点,这 ...

  6. 当双方Visual studio windows SDK不一样的时候的解决办法

    一. 把以前的SDK全部变成你的SDK 二.去重新装一个SDK版本和以前SDK一样的(这种解决办法太麻烦)

  7. SprigBoot中的 WebMvcConfigurer与 WebMvcConfigurerAdapter和 WebMvcConfigurationSupport

    WebMvcConfigurationAdapter 过时? 在SpringBoot2.0之后的版本中WebMvcConfigurerAdapter过时了,所以我们一般采用的是如下的两种的解决的方法. ...

  8. DBMS的四大特性

  9. PHP--自动回调接口,分批修改数据

    /** * 修复 a表 生日格式问题 * @author qin */ public function update_birthday_one() { $this->load->model ...

  10. ms12-020复现-xp蓝屏

    漏洞名:MS12-020(全称:Microsoft windows远程桌面协议RDP远程代码执行漏洞) 介绍:RDP协议是一个多通道的协议,让用户连上提供微软终端机服务的电脑. windows在处理某 ...