题目分析:

首先考虑无数条的情况。出现这种情况一定是一条合法路径经过了$ 0 $环中的点。那么预先判出$ 0 $环中的点和其与$ 1 $和$ n $的距离。加起来若离最短路径不超过$ k $则输出$ -1 $,否则这些点必定不被经过,接着dp后效性消失。由于每条边转移了$ k $次它的起点到终点的状态,所以总时间复杂度为$ O(n+mk) $,可以通过所有数据。

代码:

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
using namespace std; typedef pair<int,int> pr; const int maxn = ; int n,m,k,p;
vector<pair<int,int> > g[maxn],rg[maxn];
vector <int> ng[maxn]; int dfn[maxn],low[maxn],instack[maxn],scc[maxn],cl;
int f[maxn][],arr[maxn][];
stack <int> sta; void init(){
memset(dfn,,sizeof(dfn));
memset(arr,,sizeof(arr));
memset(low,,sizeof(low));
memset(instack,,sizeof(instack));
memset(scc,,sizeof(scc));
memset(f,,sizeof(f));
cl = ;
} void tarjan(int now){
low[now] = dfn[now] = ++cl;
sta.push(now);
for(int i=;i<ng[now].size();i++){
int k = ng[now][i]; if(instack[k]) continue;
if(dfn[k]) { low[now] = min(low[now],dfn[k]); }
else{ tarjan(k); low[now] = min(low[now],low[k]); }
}
if(low[now] == dfn[now]){
stack<int> tpp;int num = ;
while(true){
int tp = sta.top();sta.pop();tpp.push(tp);num++;
instack[tp] = ; scc[tp]=;
if(now == tp) break;
}
if(num == ) scc[tpp.top()] = ;
}
} void read(){
scanf("%d%d%d%d",&n,&m,&k,&p);
for(int i=;i<=n;i++) g[i].clear();
for(int j=;j<=n;j++) ng[j].clear();
for(int j=;j<=n;j++) rg[j].clear();
for(int i=;i<=m;i++){
int u,v,w; scanf("%d%d%d",&u,&v,&w);
g[u].push_back(make_pair(v,w));
rg[v].push_back(make_pair(u,w));
if(w == ) ng[u].push_back(v);
}
} int res;
int d[maxn][];
priority_queue<pr,vector<pr>,greater<pr> > pq;
void solve_dist(){
memset(d,0x3f,sizeof(d));
pq.push(make_pair(,));
while(!pq.empty()){
pair<int,int> tp = pq.top();pq.pop();
if(d[tp.second][] > 1e9) d[tp.second][] = tp.first;
else continue;
for(int j=;j<g[tp.second].size();j++){
int nxt = g[tp.second][j].first,data = g[tp.second][j].second;
data += d[tp.second][];
if(data > d[nxt][]) continue;
pq.push(make_pair(data,nxt));
}
}
res = d[n][];
pq.push(make_pair(,n));
while(!pq.empty()){
pair<int,int> tp = pq.top();pq.pop();
if(d[tp.second][] > 1e9) d[tp.second][] = tp.first;
else continue;
for(int j=;j<rg[tp.second].size();j++){
int nxt = rg[tp.second][j].first,data = rg[tp.second][j].second;
data += d[tp.second][];
if(data > d[nxt][]) continue;
pq.push(make_pair(data,nxt));
}
}
} void dfs(int now,int lw){
if(arr[now][lw]) return;
int nowd = d[now][]+lw;arr[now][lw] = ;
for(int j=;j<rg[now].size();j++){
int nxt = rg[now][j].first,data = rg[now][j].second;
if(scc[nxt])continue;
int nd = nowd-data; nd -= d[nxt][];
if(nd < ) continue;
if(nd > k) continue;
dfs(nxt,nd);
f[now][lw] += f[nxt][nd]; f[now][lw] %= p;
}
} void work(){
for(int i=;i<=n;i++) if(!dfn[i]) tarjan(i);
if(scc[]||scc[n]) {puts("-1");return;} solve_dist(); for(int i=;i<=n;i++)
if(scc[i]) if(d[i][]+d[i][]<=res+k){puts("-1");return;} f[][] = ;arr[][] = ;int ans = ;
for(int i=;i<=k;i++) {
dfs(n,i);ans += f[n][i]; ans %= p;
}
printf("%d\n",ans);
} int main(){
int t; scanf("%d",&t);
while(t--){ init(); read(); work(); }
return ;
}

[NOIP2017] 逛公园 【最短路】【强连通分量】的更多相关文章

  1. [NOIP2017]逛公园 最短路+拓扑排序+dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的有向图,边权为非负整数.求满足路径长度小于等于 $1$ 到 $n$ 最短路 $+k$ 的 $1$ 到 $n$ 的路径条数模 $p$ ,如果有无数条则输出 ...

  2. [NOIP2017]逛公园 最短路图 拓扑序DP

    ---题面--- 题解: 挺好的一道题. 首先我们将所有边反向,跑出n到每个点的最短路,然后f[i][j]表示从i号节点出发,路径长比最短路大j的方案数. 观察到,如果图中出现了0环,那么我们可以通过 ...

  3. [NOIP2017] 逛公园 (最短路,动态规划&记忆化搜索)

    题目链接 Solution 我只会60分暴力... 正解是 DP. 状态定义: \(f[i][j]\) 代表 \(1\) 到 \(i\) 比最短路长 \(j\) 的方案数. 那么很显然最后答案也就是 ...

  4. [NOIP2017] 逛公园

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

  5. 【比赛】NOIP2017 逛公园

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

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

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

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

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

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

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

  9. Luogu P3953 逛公园(最短路+记忆化搜索)

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

  10. [NOIP2017]逛公园 题解

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

随机推荐

  1. 朱晔和你聊Spring系列S1E5:Spring WebFlux小探

    阅读PDF版本 本文会来做一些应用对比Spring MVC和Spring WebFlux,观察线程模型的区别,然后做一下简单的压力测试. 创建一个传统的Spring MVC应用 先来创建一个新的web ...

  2. 解决React通过ajax加载数据更新页面不加判断会报错的问题

    通过AJAX加载数据是一个很普遍的场景.在React组件中如何通过AJAX请求来加载数据呢?首先,AJAX请求的源URL应该通过props传入:其次,最好在componentDidMount函数中加载 ...

  3. python之psutil模块详解(Linux)--小白博客

    Python-psutil模块 windows系统监控实例,查询 https://www.cnblogs.com/zhou2019/p/10567282.html 1.简单介绍 psutil是一个跨平 ...

  4. Golang-教程

    http://www.runoob.com/go/go-environment.html https://www.pythonav.cn/

  5. 全局关键字搜索:Element UI Table内容过滤\jQuery过滤器fastLiveFilter插件\BootstrapVue插件;

    ```html data:{ resultMaster: [], otableData:[], schfilter:'' } watch: { schfilter: function(val, old ...

  6. (第十三周)Final阶段成员贡献分

    项目名:食物链教学工具 组名:奋斗吧兄弟 组长:黄兴 组员:李俞寰.杜桥.栾骄阳.王东涵 个人贡献分=基础分+表现分 基础分=5*5*0.5/5=2.5 成员得分如下: 成员 基础分 表现分 个人贡献 ...

  7. IBM的淘汰之路

    BM曾经在计算领域独领风骚,但是90年被PC产业链上的微软.英特尔等厂商围殴,遭遇最严重的危机; 今天在云计算市场,IBM曾在遭遇同样的危机,这一次不知道它能否安然度过; IBM收购红帽转向混合云,是 ...

  8. 项目笔记-SC01

    项目启动已有两周,从分析需求到系统设计,文档性工作比较多,只是文档参考比较少,相对的标准就不好界定了. 计划开发时间理论上是按部就班的,没什么变化,可能真正进入开发阶段才会遇到一些问题吧,有些问题就是 ...

  9. Django中CBV的执行顺序之源码解析

    浅析Django中的CBV的执行顺序 下图为CBV方式的执行顺序,大概执行流程如下: 其中浅蓝色为在假设自己写的类,即Test类中没有dispatch方法的情况下的执行顺序,当自己的类中有dispat ...

  10. 解决jenkins运行磁盘满的问题

    解决jenkins运行磁盘满的问题 - ling811的专栏 - CSDN博客 https://blog.csdn.net/ling811/article/details/74991899 1.自动丢 ...