记忆化搜索

跑一次反向的最短路求出MinDis(u,n)MinDis(u,n)MinDis(u,n)

f[u][k]f[u][k]f[u][k]表示dis(u,n)&lt;=MinDis(u,n)+dis(u,n)&lt;=MinDis(u,n)+kdis(u,n)&lt;=MinDis(u,n)+dis(u,n)&lt;=MinDis(u,n)+kdis(u,n)<=MinDis(u,n)+dis(u,n)<=MinDis(u,n)+k的方案数,答案就是f[1][K]f[1][K]f[1][K]

考虑egde(u,v,w)egde(u,v,w)egde(u,v,w)

同样的道理走这条边的话, dis(v,n)=MinDis(v,n)+w−MinDis(u,n)dis(v,n)=MinDis(v,n)+w-MinDis(u,n)dis(v,n)=MinDis(v,n)+w−MinDis(u,n)

f[u][k]=∑f[v][k−(MinDis(v,n)−MinDis(u,n)+w)]f[u][k]=∑f[v][k-(MinDis(v,n)-MinDis(u,n)+w)]f[u][k]=∑f[v][k−(MinDis(v,n)−MinDis(u,n)+w)]

⇒f[u][k]=∑f[v][k−(MinDis(v,n)−MinDis(u,n)+w)]f[u][k]=∑f[v][k−(MinDis(v,n)−MinDis(u,n)+w)]f[u][k]=∑f[v][k−(MinDis(v,n)−MinDis(u,n)+w)]

这样怎么判000环呢?只要在搜索的时候记录个instackinstackinstack就okokok了

如果当前的转状态还在搜索的栈中就可以直接返回−1-1−1了

AC code:

#include<bits/stdc++.h>
using namespace std; inline void read(int &num)
{
char ch; int flag=1;
while(!isdigit(ch=getchar()))if(ch=='-')flag=-flag;
for(num=ch-'0';isdigit(ch=getchar());num=num*10+ch-'0');
num*=flag;
} const int MAXN = 100005;
const int MAXM = 200005;
const int MAXK = 55; int n, m, k, p, f[MAXN][MAXK];
bool instk[MAXN][MAXK]; int fir[MAXN], to[MAXM], nxt[MAXM], wt[MAXM], cnt;
int rfir[MAXN], rto[MAXM], rnxt[MAXM], rwt[MAXM], rcnt; inline void Add(int u, int v, int w) { to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt; wt[cnt] = w; }
inline void rAdd(int u, int v, int w) { rto[++rcnt] = v; rnxt[rcnt] = rfir[u]; rfir[u] = rcnt; rwt[rcnt] = w; } int dis[MAXN];
bool inq[MAXN];
queue<int>Q;
void spfa(int T)
{
memset(dis, 0x7f, sizeof dis);
dis[T] = 0; inq[T] = 1; Q.push(T);
while(!Q.empty())
{
int u = Q.front(); inq[u] = 0; Q.pop();
for(int i = rfir[u]; i; i = rnxt[i])
if(dis[rto[i]] > dis[u] + rwt[i])
{
dis[rto[i]] = dis[u] + rwt[i];
if(!inq[rto[i]])
inq[rto[i]] = 1, Q.push(rto[i]);
}
}
} int dfs(int u, int now)
{
if(instk[u][now]) return -1;
if(f[u][now]) return f[u][now];
instk[u][now] = 1;
if(u == n) f[u][now] = 1;
for(int i = fir[u], tmp; i; i = nxt[i])
if(dis[to[i]]-dis[u]+wt[i] <= now)
{
if((tmp=dfs(to[i], now-dis[to[i]]+dis[u]-wt[i])) == -1) return f[u][now] = -1;
(f[u][now] += tmp) %= p;
}
return instk[u][now] = 0, f[u][now];
} int main ()
{
int T, x, y, z;
read(T);
while(T--)
{
memset(f, 0, sizeof f);
memset(instk, 0, sizeof instk);
memset(fir, 0, sizeof fir); cnt = 0;
memset(rfir, 0, sizeof fir); rcnt = 0;
read(n), read(m), read(k), read(p);
for(int i = 1; i <= m; i++)
{
read(x), read(y), read(z);
Add(x, y, z), rAdd(y, x, z);
}
spfa(n);
printf("%d\n", dfs(1, k));
}
}

【NOIP2017】逛公园 D1 T3的更多相关文章

  1. 【题解】NOIP2017逛公园(DP)

    [题解]NOIP2017逛公园(DP) 第一次交挂了27分...我是不是必将惨败了... 考虑这样一种做法,设\(d_i\)表示从该节点到n​节点的最短路径,\(dp(i,k)\)表示从\(i\)节点 ...

  2. [NOIP2017] 逛公园

    [NOIP2017] 逛公园 题目大意: 给定一张图,询问长度 不超过1到n的最短路长度加k 的1到n的路径 有多少条. 数据范围: 点数\(n \le 10^5\) ,边数\(m \le 2*10^ ...

  3. 【比赛】NOIP2017 逛公园

    考试的时候灵光一闪,瞬间推出DP方程,但是不知道怎么判-1,然后?然后就炸了. 后来发现,我只要把拓扑和DP分开,中间加一个判断,就AC了,可惜. 看这道题,我们首先来想有哪些情况是-1:只要有零环在 ...

  4. NOIP2017逛公园(dp+最短路)

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

  5. NOIP2017 逛公园 题解报告 【最短路 + 拓扑序 + dp】

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

  6. [NOIP2017]逛公园 题解

    我连D1T3都不会我联赛完蛋了 题目描述 策策同学特别喜欢逛公园.公园可以看成一张 N 个点 M 条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口, N 号点是公园的出口,每条边有一个非负 ...

  7. [NOIP2017] 逛公园 解题报告(DP)

    我很不想说 在我的AC代码上我打了表,但实在没有办法了.莫名的8,9个点RE.然而即便是打表...也花了我很久. 这大概是NOIP2017最难的题了,为了让不懂的人更容易理解,这篇题解会比较详细 我的 ...

  8. Luogu P3953 [NOIP2017]逛公园

    题目 首先我们跑出从\(1\)出发的最短路\(d1\)和反图上从\(n\)出发的最短路\(dn\). 然后我们处理出长度不超过\(d1_n+k\)的最短路边集,给它拓扑排序. 如果存在环,那么这个环一 ...

  9. [NOIP2017] 逛公园 【最短路】【强连通分量】

    题目分析: 首先考虑无数条的情况.出现这种情况一定是一条合法路径经过了$ 0 $环中的点.那么预先判出$ 0 $环中的点和其与$ 1 $和$ n $的距离.加起来若离最短路径不超过$ k $则输出$ ...

随机推荐

  1. c++11多线程记录3: 数据争用和Mutex的使用

    https://www.youtube.com/watch?v=3ZxZPeXPaM4 学习视频 数据争用 简单来说就是存在多个线程同时对某个共同的对象进行读写(至少有一个线程在做写操作),造成读取这 ...

  2. Django框架之第八篇(模型层补充)--数据库的查询与优化:only/defer,select_related与prefetch_related,事务

    在设置外键字段时需要注意: 当你使用django2.x的版本时候,在建立外键关系时,需要你手动添加几个关键点参数 models.cascade #设置级联删除 db_constraints 数据库查询 ...

  3. 【数据结构】11.java源码关于TreeMap

    目录 1.TreehMap的内部结构 2.TreehMap构造函数 3.元素新增策略 4.元素删除 5.元素修改和查找 6.特殊操作 7.扩容 8.总结 1.TreeMap的内部结构 首先确认一点,t ...

  4. 【题解】Luogu P5338 [TJOI2019]甲苯先生的滚榜

    原题传送门 这题明显可以平衡树直接大力整,所以我要说一下线段树+树状数组的做法 实际线段树+树状数组的做法也很暴力 我们先用树状数组维护每个ac数量有多少个队伍.这样就能快速求出有多少队伍ac数比现在 ...

  5. 全栈项目|小书架|服务器端-NodeJS+Koa2 实现点赞功能

    效果图 接口分析 通过上面的效果图可以看出,点赞入口主要是在书籍的详情页面. 而书籍详情页面,有以下几个功能是和点赞有关的: 获取点赞状态 点赞 取消点赞 所以项目中理论上与点赞相关的接口就以上三个. ...

  6. dp的平行四边形优化

    证明过程转载自charliezhi2007的博客 题目链接 备用链接 分析:一道区间dp,状态转移方程\(dp[i][j]=min(dp[i][j],dp[i][s]+dp[s+1][j]+sum[j ...

  7. pyhon opencv mojave 摄像头报错

    https://blog.csdn.net/renzibei/article/details/82998933 参考了上面博主的例子,才明白. Mac macOS 10.14 Mojave Xcode ...

  8. 如何删除mysql注释

    Linux命令删除注释 先把库表导出成一个.sql文件,然后使用sed命令删除注释.此种适用于mysql端口不开外网的情况. $ cat create_table.sql create table t ...

  9. ES6 新增集合----- Set 和Map

    Sets 和数组一样,都是一些有序值的的集合,但是Sets 和数组又有所不同,首先Sets 集合中不能存有相同的值,如果你向Sets 添加重复的值,它会忽略掉, 其次Sets 集合的作用也有所不同,它 ...

  10. 数组的push()、pop()、shift()和unshift()方法

    JavaScript的数组是一个拥有堆栈和队列自身优点的global对象.也就是说JavaScript数组可以表现的像栈(LIFO)和队列(FIFO)一样操作.这也是JavaScript数组强大的可操 ...