题目: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+5,M=2e5+5,S=55,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=0,int t=0,int w=0):nxt(n),to(t),w(w) {}
}ed[M],ted[M];
int rdn()
{int ret=0;char ch=getchar();while(ch>'9'||ch<'0')ch=getchar();while(ch>='0'&&ch<='9')(ret*=10)+=ch-'0',ch=getchar();return ret;
}
priority_queue<pair<int,int> >q;
void dj()
{memset(dis,0x3f,sizeof dis);dis[1]=0;memset(vis,0,sizeof vis);q.push(make_pair(-dis[1],1));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]=1;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]=0;memset(vis,0,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]=1;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=1;return -1;}if(f[cr][k])return f[cr][k];if(cr==n)f[cr][k]=1;//别return f[cr]=1,万一在终点连了一个0环 gx[cr][k]=1;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 -1;}gx[cr][k]=0;//!return f[cr][k];
}
int main()
{T=rdn();while(T--){memset(hd,0,sizeof hd);xnt=0;memset(thd,0,sizeof thd);tnt=0;n=rdn();m=rdn();K=rdn();mod=rdn();int x,y,z;for(int i=1;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,0,sizeof f);memset(gx,0,sizeof gx);flag=0;ans=dfs(1,0);if(flag)ans=-1;printf("%d\n",ans);}return 0;
}

转载于:https://www.cnblogs.com/Narh/p/9382799.html

洛谷3953 (NOIp2017) 逛公园——记忆化搜索+用栈判0环相关推荐

  1. 洛谷3953:逛公园——题解

    https://www.luogu.org/problemnew/show/P3953 策策同学特别喜欢逛公园.公园可以看成一张n个点m条边构成的有向图,且没有自环和重边.其中1号点是公园的入口,n号 ...

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

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

  3. 洛谷P1141 01迷宫【记忆化搜索】

    题目链接:P1141 01迷宫 程序说明: 可以用bfs来做,但是数据毒瘤,如果每次询问都运行一次bfs,会有三个TLE..可以将路途经过的点储存起来并且记录答案,如果询问的点已经被记录了答案,直接输 ...

  4. 洛谷 3953 NOIP2017提高组Day1 T3 逛公园

    [题解] 先建反向图,用dijkstra跑出每个点到n的最短距离dis[i] 设f[u][k]表示dis(u,n)<=mindis(u,n)+k的方案数.对于边e(u,v,w),走了这条边的话需 ...

  5. 洛谷P4513 小白逛公园

    区间最大子段和模板题.. 维护四个数组:prefix, suffix, sum, tree 假设当前访问节点为cur prefix[cur]=max(prefix[lson],sum[lson]+pr ...

  6. CCF CSP 点亮数字人生(记忆化搜索+拓扑排序判环)

    题目背景 土豪大学的计算机系开了一门数字逻辑电路课,第一个实验叫做"点亮数字人生",要用最基础的逻辑元件组装出实际可用的电路.时间已经是深夜了,尽管实验箱上密密麻麻的连线已经拆装了 ...

  7. 洛谷 P3953 [NOIP2017 提高组] 逛公园

    开始刷题单啦~,这部分的洛谷好题作为个人训练记录和以后复习用,有兴趣的可以一起做做 题目链接:P3953 [NOIP2017 提高组] 逛公园 题意都是中文就不翻译了 题解:这是一道记忆化+搜索的题目 ...

  8. 【NOIP2017】逛公园 拆点最短路+拓扑(记忆化搜索

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

  9. LOJ #2316「NOIP2017」逛公园【最短路】【记忆化搜索】

    dis[i]dis[i]dis[i]表示111号点到iii号点的最短距离,用spfaspfaspfa跑一遍即可. 考虑如何设定状态. 注意到题意要的是小于等于dis[n]+Kdis[n]+Kdis[n ...

最新文章

  1. mysql 40101
  2. BZOJ-1008 越狱 数论快速幂
  3. Java开发微信的6个步骤
  4. Win10系统下安装ubuntu系统
  5. Java中在时间戳计算的过程中遇到的数据溢出问题
  6. hibernate注释映射_Hibernate一对一映射示例注释
  7. SuperPoint学习(一)
  8. 内推 | 高级数据分析师(base:杭州)
  9. SMBUS和i2cBus,PMBus 区别
  10. 【GPU精粹与Shader编程】(六) 《GPU Gems 3》:真实感皮肤渲染技术总结
  11. 谷歌hosts laod
  12. compass项目配置文件config.rb
  13. Linux必备工具————虚拟机
  14. android webView显示PDF文件
  15. [Ubuntu 16.04] [Memos] install samba
  16. 织梦模板文件不存在,无法解析文档的最快解决方法
  17. spark中repartition, coalesce, partitionBy, repartitionAndSortWithinPartitions 四种重分区算子
  18. ENSP华为模拟器:基础命令及简写
  19. html语言中的强制性换行是,html中的div、td 、p 等容器内强制换行和不换行的实现方法...
  20. 欢迎访问我的个人博客:www.zou8944.com

热门文章

  1. 【数据结构】栈的编写以及栈的简单应用
  2. tab和TabHost
  3. asp.net添加自定义用户控件并传值
  4. 查询各种物流运输信息
  5. com.mysql.jdbc.PacketTooBigException,及mysql 设置 max_allow_packet
  6. iOS10推送适配完整说明
  7. ScrollView常用属性汇总
  8. ORACLE DATAGUARD 数据库---创建逻辑备用数据库
  9. C++根据.h文件批量生成需要的函数框架
  10. 51CTO博客——架起我与读者沟通、见面的桥梁[博友话题]