洛谷题目传送门

又是一年联赛季。NOIP2017至此收官了。

这个其实是比较套路的图论DP了,但是细节有点恶心。

先求出\(1\)到所有点的最短路\(d1\),和所有点到\(n\)的最短路\(dn\)。

设\(f_{i,j}\)表示\(i\)号点,所有与\(d1\)差距不超过\(j\)的路径条数。转移的时候肯定是从小到大枚举\(j\),再枚举边转移。显然每条边都有一个\(\Delta\)值,为\(d1_x-d1_y+w\),含义就是强制经过这条边的最短路长度相较于原最短路长度的增量。于是有转移式\(f_{x,j}\rightarrow f_{y,j+\Delta}\)。

显然上面的转移,要沿着最短路的方向转移,所以要按\(d1\)从小到大考虑每个点的出边。

没有\(0\)的边就可以直接开始做了,可偏偏就是有啊qwq。

首先来判无解,首先要有个\(0\)环,其次要有一条经过环的、长度小于等于\(d1_n+k\)的路径。考虑在所有\(0\)边的子图上拓扑排序,剩下未出队的肯定在环上,对剩下的点检查一遍有没有\(d1_x+dn_x\le d1_n+k\)的。

接下来,还别忘了处理被\(0\)边所连起来的点的转移顺序。这个时候如果剩下环肯定贡献不到答案,需要处理的就是一些DAG上的点的顺序了。显然来一组拓扑序就可以了,拓扑排序的时候顺便搞搞。转移顺序就用\(d1\)和拓扑序双关键字确定好了。

时间复杂度\(O(T((n+m)\log m+kn))\)

#include<bits/stdc++.h>
#define LL long long
#define RG register
#define R RG int
#define G if(++ip==ie)fread(ip=buf,1,SZ,stdin)
using namespace std;
const int SZ=1<<19,N=1e5+9,M=4e5+9;
int n,m,k,YL,p,he[N],re[N],ne[M],to[M],w[M],deg[N],q[N],d1[N],dn[N],o[N],ord[N],f[N][51];
bool vis[N];
struct Node{
int d,x;
inline bool operator<(Node a)const{
return d>a.d||(d==a.d&&o[x]>o[a.x]);
}
};
priority_queue<Node>Q;
char buf[SZ],*ie=buf+SZ,*ip=ie-1;
inline int in(){
G;while(*ip<'-')G;
R x=*ip&15;G;
while(*ip>'-'){x*=10;x+=*ip&15;G;}
return x;
}
inline void add(R&x,R y){
if((x+=y)>=YL)x-=YL;
}
void dij(R*d,R*he,R x){//最短路
memset(d+1,127,4*n);memset(vis+1,0,n);
Q.push((Node){d[x]=0,x});
while(!Q.empty()){
x=Q.top().x;Q.pop();
if(vis[x])continue;
vis[x]=1;
if(d==d1)ord[++p]=x;//记录转移顺序
for(R y,i=he[x];i;i=ne[i])
if(d[y=to[i]]>d[x]+w[i])
Q.push((Node){d[y]=d[x]+w[i],y});
}
}
int main(){
for(R T=in();T;--T){
n=in();m=in();k=in();YL=in();
R x,y,t=0;
for(R i=1;i<=m;++i){
x=in(),y=in();//建双向边
ne[i]=he[x];to[he[x]=i]=y;i+=m;
ne[i]=re[y];to[re[y]=i]=x;i-=m;
if(!(w[i]=w[i+m]=in()))++deg[y];
}
for(R i=1;i<=n;++i)//拓扑排序
if(!deg[i])q[++t]=i;
for(R h=0;h<=t;++h){
o[x=q[h]]=h;
for(R i=he[x];i;i=ne[i])
if(!w[i]&&!--deg[to[i]])q[++t]=to[i];
}
dij(d1,he,1);dij(dn,re,n);
for(R i=1;i<=n;++i)
if(deg[i]&&d1[i]+dn[i]<=d1[n]+k){puts("-1");goto F;}
for(x=1;x<=n;++x)//重赋边权为Δ
for(R i=he[x];i;i=ne[i])
w[i]+=d1[x]-d1[to[i]];
f[1][0]=1;//DP开始
for(R j=0;j<=k;++j)
for(R i=1;i<=n;++i)
if(f[x=ord[i]][j])
for(R i=he[x];i;i=ne[i])
if(j+w[i]<=k)add(f[to[i]][j+w[i]],f[x][j]);
for(R i=x=0;i<=k;++i)add(x,f[n][i]);
printf("%d\n",x);
F:memset(he+1,0,4*n);memset(re+1,0,4*n);
memset(o+1,0,4*n);memset(deg+1,0,4*n);memset(ord+1,0,4*n);
memset(f+1,0,4*51*n);p=0;
}
return 0;
}

洛谷P3953 逛公园(NOIP2017)(最短/长路,拓扑排序,动态规划)的更多相关文章

  1. 洛谷P3953 逛公园 [noip2017] 图论+dp

    正解:图论(最短路)+dp(记忆化搜索) 解题报告: 这题真的是个好东西! 做了这题我才发现我的dij一直是错的...但是我以前用dij做的题居然都A了?什么玄学事件啊...我哭了TT 不过其实感觉还 ...

  2. 洛谷P3953 逛公园

    DP+图论大毒瘤. 推荐这个博客. 先跑两遍最短路,搞掉一些无用点. 然后选出最短路上的边,做拓扑排序. 然后每层DP. 具体看代码. 用到的数组较多,记得清空. #include <cstdi ...

  3. 洛谷P3953逛公园

    题目 作为\(NOIp2017D1T3\) 这个题还是很良心的,至少相对于\(NOIp2018\)来说,希望\(NOIp2019\)不会这么坑吧. 这个题可以作为记忆化搜索的进阶题了,做这个题的方法也 ...

  4. 洛谷 P3953 逛公园

    题目链接 思路 首先没有0边,且k为0的情况就是最短路计数. 如果k不为0,看到k<=50,想到dp. 设f[u][i]表示到达u点比最短路多走i的路径数,转移到v点. f[u][i]+=f[v ...

  5. 2018.11.01 洛谷P3953 逛公园(最短路+dp)

    传送门 设f[i][j]f[i][j]f[i][j]表示跟最短路差值为iii当前在点jjj的方案数. in[i][j]in[i][j]in[i][j]表示在被选择的集合当中. 大力记忆化搜索就行了. ...

  6. 洛谷P3953 逛公园(dp 拓扑排序)

    题意 题目链接 Sol 去年考NOIP的时候我好像连最短路计数都不会啊qwq.. 首先不难想到一个思路,\(f[i][j]\)表示到第\(i\)个节点,与最短路之差长度为\(j\)的路径的方案数 首先 ...

  7. 洛谷 P3953 逛公园【spfa+记忆化dfs+bfs】

    spfa预处理出最短路数组dis,然后反向建边bfs出ok[u]表示u能到n点 然后发现有0环的话时候有inf解的,先dfs找0环判断即可 然后dfs,设状态f[u][v]为到u点,还可以跑最短路+v ...

  8. LOJ P3953 逛公园 NOIP dp 最短路 拓扑排序

    https://www.luogu.org/problemnew/show/P3953 开o2过了不开o2re一个点...写法如题 顺便一提这道题在我校oj是a不了的因为我校土豆服务器速度奇慢1s时限 ...

  9. 洛谷 P1053 逛公园 解题报告

    P3953 逛公园 问题描述 策策同学特别喜欢逛公园. 公园可以看成一张\(N\)个点\(M\)条边构成的有向图,且没有自环和重边.其中1号点是公园的入口,\(N\)号点是公园的出口,每条边有一个非负 ...

随机推荐

  1. Linux安装Apache常见报错(二)

    配置Apache提示报错configure error: APR could not be located. Please use the --with-apr option. 解决办法: ./con ...

  2. 亲测可以永久破解2018版本的pycharm

    pycharm是很强大的开发工具,但是每次注册着实让人头疼.网络上很多注册码.注册服务器等等.但都只是一年或者不能用:为次有如下解决方案.亲测有效!!! 如果想让pycharm永久被激活,比如截止日到 ...

  3. Vue2.0 搭建Vue脚手架(vue-cli)

    介绍 Vue.js是一套构建用户界面的渐进式框架.Vue 只关注视图层,采用自底向上增量开发的设计.Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件. 阅读之前需要了解的知 ...

  4. Django 内的母版-子html规则

    一.母版 在实际应用中,在开发一个网站时,从首页到主页.到目录页,等等!有时候,我们大部分基础网页头.边框.侧边框.基础css.js等复用性很高,如果每一个html都要独立去写的话,就太麻烦了. 而把 ...

  5. 在Linux添加PYTHONPATH方法以及修改环境变量方法

    Linux下设置环境变量有三种方法,一种用于当前终端,一种用于当前用户,一种用于所有用户: 一:用于当前终端: 在当前终端中输入: export PATH=$PATH:<你的要加入的路径> ...

  6. JEECG SSO kisso

    kisso: java 基于 Cookie 的 SSO 中间件 kisso https://gitee.com/baomidou/kisso kisso首页.文档和下载 - 基于 Cookie 的 S ...

  7. IdentityServer4【QuickStart】之使用asp.net core Identity

    使用asp.net core Identity IdentityServer灵活的设计中有一部分是可以将你的用户和他们的数据保存到数据库中的.如果你以一个新的用户数据库开始,那么,asp.net co ...

  8. CMake--变量

    1.一般变量 1)CMake变量引用的方式 使用${}进行变量的引用.例如: ${PROJECT_NAME} #返回项目名称 在 IF 等语句中,是直接使用变量名而不通过${}取值. 2)cmake自 ...

  9. String类内存空间详解

    java.lang.String类内存问题详解 字符串理解的难点在于其在堆内存空间上的特殊性,字符串String对象在堆内存上有两种空间: 字符串池(String pool):特殊的堆内存,专门存放S ...

  10. class面向对象-1

    一.基本定义 class cl(object): def __init(self,var) self.var=var def func(self,i) print('%s is in %s'%(i,s ...