主要思路:记忆化搜索,最短路

观察数据范围发现K规模较小,可以当做状态

N值较大,使用前向星链式存边

无限种方案,简单的分析可以得到:

如果没有回路(环),在不考虑路程的情况下只有有限的方案
在有回路的情况下,积累路径权,仍然是有限的方案

综上无限方案是路径长度为0组成的环

两组dfs,void dfs0(long long int x)用作查找0环,dfs(int x,int sum)查找方案; 正反两遍迪杰斯特拉,方便剪枝和查找0环。

在dfs0的扩展状态中,只有边权为0,且距离点1距离相等才扩展状态。

以下巨长奇丑代码

#include <iostream>
#include <fstream>
#include <cstdio>
#include <string.h>
#define ce cout<<endl;
using namespace std;
const long long int maxn=100001,maxm=200001,INF=2002102020;
const long long int NONE=0;
long long int en,T,n,m,e0,x,y,l,k,p;
long long int head[maxn],mdis[maxn],mdisf[maxn],ans,mlen,last[maxn+2][55];
bool vis[maxn],v0[maxn],fl;
int qread(){int x=0;char ch=getchar();while(ch>'9'||ch<'0')ch=getchar();while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x;
}//读入优化
struct edg{int fr,to,len,nxt;
};
edg e[maxm];
void adg( long long int x, long long int y, long long int l){en++;e[en].fr=x;e[en].to=y;e[en].len=l;e[en].nxt=head[x];head[x]=en;
}//添加边
void dfs0( long long int x){if(fl)return;//cout<<x<<endl;if(mdisf[x]==INF)return;if(!v0[x]){fl=true;//fl标记是否有零环,当某结点两次被查找时,它处在一个零环return;}v0[x]=false;//值得注意的是,如果零环无法到达,那么它不会影响结果。因此若距离是无穷大,则无须扫描for( long long int i=head[x];i>0;i=e[i].nxt){if(e[i].len||(mdis[x]!=mdis[e[i].to]))continue;//if(v0[e[i].to]){dfs0(e[i].to);//}}v0[x]=true;
}
void dfs( long long int x,long long int sum){if(sum-mdis[x]<0||sum-mdis[x]>50) return;//记忆化搜索,如果曾经搜到这个状态,直接ans+对应值if(sum+mdisf[x]>mlen)return;if(sum-mdis[x]>k)return;//mdis,mdisf分别存储1-i,n-i的最短路。if(sum-mdis[x]>=0&&sum-mdis[x]<=50)if(last[x][sum-mdis[x]]>-1){ans=(last[x][sum-mdis[x]]+ans)%p;return;}int rec=ans;if(x==n)ans=(ans+1)%p;//cout<<x<<endl;for(int i=head[x];i>0;i=e[i].nxt){dfs(e[i].to,sum+e[i].len);}last[x][sum-mdis[x]]=(ans-rec)%p;//新增的ans值就是记忆化数组中的存储
}int main(){// freopen("3953_tle.txt","r",stdin);T=qread();while(T--){ans=0;fl=false;en=e0=0;n=qread();m=qread();k=qread();p=qread();memset(head,-1,sizeof(head));memset(mdis,0x3f,sizeof(mdis));memset(vis,1,sizeof(vis));memset(v0,1,sizeof(v0));for(int i=1;i<=m;i++){x=qread();y=qread();l=qread();adg(x,y,l);}  mdis[1]=0;int f=0;while(f<n){//正向求最短路f++;int minn=INF,t;for(int i=1;i<=n;i++){if((mdis[i]<minn)&&vis[i]){t=i;minn=mdis[i];}}vis[t]=false;for(int i=head[t];i>0;i=e[i].nxt){if(vis[e[i].to]&&(e[i].len+minn<mdis[e[i].to]))mdis[e[i].to]=e[i].len+minn;}}en=0;memset(head,-1,sizeof(head));for(int i=1;i<=m;i++){adg(e[i].to,e[i].fr,e[i].len);}//把所有边翻转for(int i=1;i<=n;i++){mdisf[i]=INF;vis[i]=true;}mdisf[n]=0;f=1;//反向求最短路while(f<n){f++;int minn=INF,t;for(int i=1;i<=n;i++){if(vis[i]&&(mdisf[i]<minn)){minn=mdisf[i];t=i;}}vis[t]=false;for(int i=head[t];i>0;i=e[i].nxt)if(vis[e[i].to]&&mdisf[e[i].to]>minn+e[i].len)mdisf[e[i].to]=minn+e[i].len;}for(int i=1;(i<=n)&&(!fl);i++){if((mdis[i]!=INF)&&(mdisf[i])!=INF){dfs0(i);//cout<<endl;}}if(fl){cout<<-1<<endl;continue;}en=0;memset(head,-1,sizeof(head));for(int i=1;i<=m;i++){adg(e[i].to,e[i].fr,e[i].len);}mlen=mdis[n]+k;memset(last,-1,sizeof(last));dfs(1,0);cout<<ans%p<<endl; }return 0;}

洛谷3953 逛公园相关推荐

  1. 洛谷 P3953 逛公园

    原题链接 题目描述 策策同学特别喜欢逛公园.公园可以看成一张 NN 个点 MM 条边构成的有向图,且没有 自环和重边.其中 11 号点是公园的入口,NN 号点是公园的出口,每条边有一个非负权值, 代表 ...

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

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

  3. 洛谷P3953 逛公园

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

  4. NOIP2017洛谷P3953:逛公园(分层图最短路、dp、拓扑)

    解析 容易想到dp 先跑一遍最短路把每个点的dis求出来 设计dpu,xdp_{u,x}dpu,x​表示结点u多走了x的方案数 dp按照dis升序排列后,从前到后转移即可 如果有0边,求出只有0边时的 ...

  5. 洛谷 P1638 逛画展

    洛谷 P1638 逛画展 题目链接 题目描述 博览馆正在展出由世上最佳的 M 位画家所画的图画. wangjy想到博览馆去看这几位大师的作品. 可是,那里的博览馆有一个很奇怪的规定,就是在购买门票时必 ...

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

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

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

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

  8. 洛谷3953 (NOIp2017) 逛公园——记忆化搜索+用栈判0环

    题目:https://www.luogu.org/problemnew/show/P3953 因为K只有50,所以想到用dp[ cr ][ j ]表示在点cr.比最短路多走了 j 的方案数.(看了TJ ...

  9. 洛谷P1638 逛画展

    题目描述 博览馆正在展出由世上最佳的 m 位画家所画的图画. 游客在购买门票时必须说明两个数字,a 和 b,代表他要看展览中的第 a 幅至第 b 幅画(包含 a,b)之间的所有图画,而门票的价钱就是一 ...

  10. 洛谷 [P1638 逛画展] (尺取法)

    Link https://www.luogu.org/problemnew/show/P1638 Description  博览馆正在展出由世上最佳的 M 位画家所画的图画.wangjy想到博览馆去看 ...

最新文章

  1. 超融合架构下的数据中心
  2. WebJars 进行 css js 资源文件管理
  3. 使用7z命名行备份VS项目
  4. 玩转html5画图 - TimeLangoliers - 博客园
  5. 王石:人生60岁才是开始
  6. 一种真正意义上的Session劫持
  7. F5 cookie值与IP地址(二):将IP地址转换成F5 cookie值
  8. Java 程序设计基础(第四版)下
  9. java 获取32位纯数字 或字母与数字结合的唯一id
  10. 前端面试题总汇、常考、笔试题等
  11. python语音聊天_语音聊天实现
  12. 计算用户的平均次日、三日和七日留存率
  13. Vmware虚拟机无法联网?
  14. 网易考拉规则引擎平台架构设计与实践
  15. 优化AWS使用成本系列之预留实例(RI)为您提供大幅折扣
  16. springboot集成shiro实现验证码校验
  17. 华为防火墙-1-安全区域
  18. 工业系统虚拟化测试平台搭建
  19. 互融云数字资产管理平台综合解决方案
  20. html5 语音导航,诺基亚推出HTML5版导航地图

热门文章

  1. 集成学习task03-偏差、方差理论、特征提取和模型超参数调优
  2. 【数据集】英文手写字母数据集处理
  3. 互盾科技:学问之道,贵在实行;圣贤之学,俱在践履
  4. Linux线程(3)——pthread_cancel()取消一个线程
  5. 1000粉丝也能在短视频直播带货中赚的盆满钵满
  6. matlab-图像腐蚀算子SE的选取
  7. JQuery的常用知识总结
  8. ARMv8的异常等级(Exception Level)以及执行状态(AArch64/AArch32)
  9. Hive一条SQL使用随机值创建测试表一百万条数据
  10. 【解决Ubuntu18.04没声音:No cards available for configuration】