洛谷题目传送门

又是一年联赛季。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. 将工程改造为SOA架构

    商城是基于soa的架构,表现层和服务层是不同的工程.所以要实现商品列表查询需要两个系统之间进行通信. 流动计算架构 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基 ...

  2. Zk搭建(Zookeeper)

      第一步: 上传----解压   tar -zxvf zookeeper-3.4.5.tar.gz----                配置zk的环境变量  ----------配置源码 vim ...

  3. laravel打印sql

    DB::connection()->enableQueryLog(); print_r(DB::getQueryLog());

  4. Spark源码编译,官网学习

    这里以spark-1.6.0版本为例 官网网址   http://spark.apache.org/docs/1.6.0/building-spark.html#building-with-build ...

  5. 关于解决Missing Number之类的算法问题

    停止刷题已经三周了,有些想念.最近总算完成了公司代码的重构,于是要继续开始学习算法. 先来看leetcode上面第268题: Given an array containing n distinct ...

  6. TField OnValidate 事件

    Occurs just before the data is written to the record buffer. Write an OnValidate event handler to va ...

  7. html5 表單屬性

    新的 form 属性: autocomplete novalidate 新的 input 属性: autocomplete autofocus form form overrides (formact ...

  8. vue自定义组件及传值

    1.使用 Vue.component() 方法注册组件 2.使用 props 属性传递参数 v-for="item in items": 遍历 Vue 实例中定义的名为 items ...

  9. js一元运算符

    否运算符(按位非):~    加1取反 console.log(~-); console.log(~-); console.log(~); //-1 void():计算表达式,但是不返回值(仅仅是不返 ...

  10. 使用cmd命令行窗口操作SqlServer

    本文主要介绍使用windows下的使用cmd命令行窗口操作Sqlserver, 首先我们可以运行 osql  ?/   ,这样就把所有可以通过CMD命令行操作sqlserver的命令显示出来 (有图有 ...