不管怎么说,这都是一道十分神仙的NOIp题

你可以说它狗,但不可以否认它就是NOIp的难度

首先这道题很显然是道图论还是一道图论三合一(最短路+拓扑+图上DP)

先考虑最短路,我们分别以\(1\)和\(n\)为起点得出与其它点的最短路(虽然NOIp应该不会卡SPFA,但还是建议写稳定的DJ)

我们先考虑把\(-1\)的情况给判掉,分析一下发现此时必定有0环(此时可以在0环上无限刷路径)

但是要注意一下,当且仅当0环上的任意一点\(i\)到\(1\)的最短路\(dis_{1,i}\)以及它到\(n\)的最短路\(dis_{i,n}\)满足\(dis_{1,i}+dis_{i,n}<=dis_{1,n}+k\),因为这个0环首先得在可行路径上

处理0环的具体操作只要把0边权的边单独拎出来做拓扑排序就好了。

然后考虑如何统计答案,我们发现\(k<=50\)。因此我们图上DP计数

设\(f_{i,j}\)表示到第\(i\)个点时,偏移量(偏移量为当前路径长度与\(dis_{1,i}\)的差)为\(j\)的方案数:

我们再枚举\(i\)可以到达的点\(p\),若\(dis_{1,i}+w+j-dis_{1,p}<=k\),然后就可以用\(f_{i,j}\)更新\(f_{p,dis_{1,i}+w+j-dis_{1,p}}\)了(\(w\)为\(i\rightarrow p\)的边权)

最后要注意的是枚举的状态顺序,我们发现对于所有的点\(i\),当它的\(dis_{1,i}\)越小时,它越早更新

特别地,当都是0权的边排序时,应该按之前的拓扑顺序排

CODE

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=100005,K=55;
struct edge
{int to,next,v;
}e[N<<1],re[N<<1];
struct Zero_edge
{int to,next;
}ze[N<<1];
struct Small
{int num,s;bool operator <(const Small x) const { return x.s<s; }
};
struct data
{int d,id,num;
}a[N];
int head[N],rhead[N],zhead[N],t,n,m,k,p,x,y,z,cnt,zcnt,ru[N],q[N],f[N][K],dis[N],INF,r[N];
bool vis[N];
priority_queue <Small> small;
inline char tc(void)
{static char fl[100000],*A=fl,*B=fl;return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{x=0; char ch; while (!isdigit(ch=tc()));while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
}
inline void write(int x)
{if (x>9) write(x/10);putchar(x%10+'0');
}
inline void clear(void)
{memset(head,-1,sizeof(head)); memset(rhead,-1,sizeof(rhead));memset(zhead,-1,sizeof(zhead)); memset(ru,0,sizeof(ru)); cnt=zcnt=0;
}
inline void add(int x,int y,int z)
{e[++cnt].to=y; e[cnt].next=head[x]; e[cnt].v=z; head[x]=cnt;
}
inline void radd(int x,int y,int z)
{re[cnt].to=y; re[cnt].next=rhead[x]; re[cnt].v=z; rhead[x]=cnt;
}
inline void zadd(int x,int y)
{ze[++zcnt].to=y; ze[zcnt].next=zhead[x]; zhead[x]=zcnt; ++ru[y];
}
inline void top_sort(void)
{register int i,H=0,T=0;for (i=1;i<=n;++i){if (!ru[i]) q[++T]=i,a[i].id=T; a[i].num=i;}while (H<T){int now=q[++H];for (i=zhead[now];~i;i=ze[i].next)if (!(--ru[ze[i].to])) q[++T]=ze[i].to,a[ze[i].to].id=T;}
}
inline void front_dijkstra(void)
{memset(dis,63,sizeof(dis)); memset(vis,0,sizeof(vis));small.push((Small){1,0}); INF=dis[0]; dis[1]=a[1].d=0;while (!small.empty()){int now=small.top().num; small.pop();if (vis[now]) continue; vis[now]=1;for (register int i=head[now];~i;i=e[i].next)if (dis[e[i].to]>dis[now]+e[i].v){a[e[i].to].d=dis[e[i].to]=dis[now]+e[i].v;small.push((Small){e[i].to,dis[e[i].to]});}}
}
inline void back_dijkstra(void)
{memset(dis,63,sizeof(dis)); memset(vis,0,sizeof(vis));small.push((Small){n,0}); dis[n]=0;while (!small.empty()){int now=small.top().num; small.pop();if (vis[now]) continue; vis[now]=1;for (register int i=rhead[now];~i;i=re[i].next)if (dis[re[i].to]>dis[now]+re[i].v){dis[re[i].to]=dis[now]+re[i].v;small.push((Small){re[i].to,dis[re[i].to]});}}
}
inline bool check(void)
{for (register int i=1;i<=n;++i)if (ru[i]&&a[i].d+dis[i]<=a[n].d+k) return 1;return 0;
}
inline bool cmp(data a,data b)
{if (a.d<b.d) return 1;if (a.d>b.d) return 0;return a.id<b.id;
}
inline void inc(int &x,int y)
{if ((x+=y)>=p) x-=p;
}
inline int DP(void)
{memset(f,0,sizeof(f)); f[1][0]=1; int ans=0;for (register int s=0;s<=k;++s){for (register int i=1;i<=n;++i){int now=a[i].num;for (register int j=head[now];~j;j=e[j].next)if (a[i].d+s+e[j].v-a[r[e[j].to]].d<=k) inc(f[e[j].to][a[i].d+s+e[j].v-a[r[e[j].to]].d],f[now][s]);}inc(ans,f[n][s]);} return ans;
}
int main()
{//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);register int i; read(t);while (t--){read(n); read(m); read(k); read(p); clear();for (i=1;i<=m;++i){read(x); read(y); read(z);add(x,y,z); radd(y,x,z); if (!z) zadd(x,y);}top_sort(); front_dijkstra(); back_dijkstra();if (check()) { puts("-1"); continue; } sort(a+1,a+n+1,cmp);for (i=1;i<=n;++i) r[a[i].num]=i;write(DP()); putchar('\n');}return 0;
}

转载于:https://www.cnblogs.com/cjjsb/p/9337052.html

Luogu P3953 逛公园相关推荐

  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. 2017noip逛公园

    2017 noip Day1 T2 逛公园 (洛谷P3953)传送门 输出输入数据自己找 这个题看到其他的大佬有用dp做的. 推荐一个大佬的讲解 本蒟蒻dp学得烂,东拼拼西凑凑勉强懂了.就发一个dfs ...

  6. 【ybt高效进阶4-4-3】【luogu P4513】公园遛狗 / 小白逛公园

    公园遛狗 / 小白逛公园 题目链接:ybt高效进阶4-4-3 / luogu P4513 题目大意 给你一个序列,要维护两个操作. 单点修改和在一个区间中找权值最大的子区间的权值. 思路 其实这个是很 ...

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

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

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

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

  9. NOIP2017逛公园

    在WA了接近20遍后,本蒟蒻终于切掉了逛公园.. 逛公园的题意为求出图中从1到n路径长度<=d(最短路)+k 的 路径条数. 这道题十分的像luogu 1608 路径统计,虽然算法完全不一样, ...

最新文章

  1. Qt + VS 【如何添加图片资源】
  2. module_init 详解
  3. 今日腊八节,祝福送上!
  4. ORACLE使用批量插入100万测试数据
  5. 疫情下的618:搜索热度已盖过双11,全民练习“直播带货”
  6. 下载地址jquery upload file demo (C#)
  7. react 把前后台的axios请求放在一起_可靠React组件设计的7个准则之SRP
  8. 漫画Linux 并发、竞态、互斥锁、自旋锁、信号量
  9. Spring Struts2 整合
  10. python中文编码查询_Python中文编码问题
  11. win10不自带扫雷,想玩扫雷怎么办?自己造一个扫雷
  12. DirectX显示流程学习小结
  13. u盘资料误删怎么恢复 怎样找回u盘里误删的文件
  14. 【锐捷】交换机,AC设备虚拟化(VSU、VAC)
  15. 【题解】 Test 买水的ACX(套路)
  16. php得到明天凌晨,PHP获得今天凌晨时间戳,明天凌晨时间戳,获取凌晨时间戳
  17. Visual Studio 2017 智能提示英文怎么切换成中文?
  18. SUSE(Linux操作系统)
  19. C++学习——如何在C++中把map存入一个txtx文件
  20. .net 邮箱验证码 邮箱验证码实现用户注册

热门文章

  1. MySQL kill操作
  2. 黄聪:PowerPoint设计编辑动画的时候图层隐藏和显示问题
  3. HttpWebRequest与HttpWebResponse进行数据采集时的注意点
  4. loc和iloc的用法汇总(完成)
  5. 电纸书kindle相关产品调研(没搞完)
  6. 基于神经网络模型的文本语义通顺度计算研究-全文复现(还没弄完)
  7. myid文件到底是否需要自己手动配置
  8. Google Drive的linux客户端使用(还没弄完)
  9. 用eval在txt中存储list,dict,tuple
  10. python聊天程序