luogu3953 [NOIp2017]逛公园 (tarjan+dijkstra+记忆化搜索)
先跑一边dijkstra算出从1到i的最短距离dis[i]
然后建反向边 从n开始记忆化搜索,(p,k)表示1到p的距离=dis[p]+k的方案数
答案就是$\sum\limits_{i=0}^{k}{(n,i)}$
考虑0环,如果我记搜的时候搜到了0环,那答案就是-1,可以先用tarjan处理一下0边 看看有哪些点在零环上
(其实也可以开个栈 做到(p,k)的时候看(p,k)是不是已经在栈中了 如果是那就是-1)
#include<bits/stdc++.h>
#define CLR(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
typedef pair<int,int> pa;
const int maxn=1e5+,maxm=2e5+,maxk=; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} struct Edge{
int b,l,ne;
}eg[maxm],neg[maxm];
struct Node{
int p,k,n;
Node(int a=,int b=,int c=){p=a,k=b,n=c;}
};
int egh[maxn],negh[maxn],ect,nect;
int dis[maxn],f[maxn][maxk];
int dfn[maxn],tot,low[maxn],stk[maxn],sh;
int N,M,K,P;
bool in0[maxn],instk[maxn],flag[maxn]; inline void adeg(int a,int b,int c){
eg[++ect].b=b,eg[ect].l=c,eg[ect].ne=egh[a],egh[a]=ect;
neg[++nect].b=a,neg[nect].l=c,neg[nect].ne=negh[b],negh[b]=nect;
} void tarjan(int x){
dfn[x]=low[x]=++tot,instk[x]=,stk[++sh]=x;
for(int i=egh[x];i;i=eg[i].ne){
if(eg[i].l) continue;
int b=eg[i].b;
if(!dfn[b]) tarjan(b),low[x]=min(low[x],low[b]);
else if(instk[b]) low[x]=min(low[x],dfn[b]);
}
if(dfn[x]==low[x]){
int n=;
for(int i=sh;stk[i]!=x;i--) n++;
while(){
instk[stk[sh]]=;
in0[stk[sh]]=n>;
if(stk[sh--]==x) break;
}
}
} priority_queue<pa,vector<pa>,greater<pa> > q;
inline void dijkstra(){
while(!q.empty()) q.pop();
CLR(flag,);CLR(dis,);dis[]=;
q.push(make_pair(,));
while(!q.empty()){
int p=q.top().second;q.pop();
if(flag[p]) continue;
flag[p]=;
for(int i=egh[p];i;i=eg[i].ne){
int b=eg[i].b;
if(dis[b]>dis[p]+eg[i].l){
dis[b]=dis[p]+eg[i].l;
q.push(make_pair(dis[b],b));
}
}
}
} inline int solve(int x,int y){
// if(f[x][y]>=0) printf("get%d %d %d\n",x,y,f[x][y]);
if(y<||y>K) return ;
if(in0[x]) return -;
if(f[x][y]>=) return f[x][y];
f[x][y]=;
for(int i=negh[x];i;i=neg[i].ne){
int b=neg[i].b;
int re=solve(b,dis[x]-dis[b]+y-neg[i].l);
if(re==-) return -;
f[x][y]+=re,f[x][y]%=P;
}
return f[x][y];
} int main(){
int i,j,k;
for(int T=rd();T;T--){
N=rd(),M=rd(),K=rd(),P=rd();
CLR(egh,);ect=;
CLR(negh,);nect=;
for(i=;i<=M;i++){
int a=rd(),b=rd(),c=rd();
adeg(a,b,c);
}
CLR(dfn,);CLR(instk,);tot=;CLR(in0,);
for(i=;i<=N;i++)
if(!dfn[i]) tarjan(i);
dijkstra();
CLR(f,-);
f[][]=;int ans=;
for(i=;i<=K;i++)
ans+=solve(N,i),ans%=P;
printf("%d\n",ans<?-:ans);
} return ;
}
luogu3953 [NOIp2017]逛公园 (tarjan+dijkstra+记忆化搜索)的更多相关文章
- Luogu P3953 逛公园(最短路+记忆化搜索)
		P3953 逛公园 题面 题目描述 策策同学特别喜欢逛公园.公园可以看成一张 \(N\) 个点 \(M\) 条边构成的有向图,且没有自环和重边.其中 \(1\) 号点是公园的入口,\(N\) 号点是公 ... 
- HDU1142 (Dijkstra+记忆化搜索)
		A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Jav ... 
- Luogu 3953[NOIP2017] 逛公园 堆优化dijkstra + 记忆化搜索
		题解 首先肯定是要求出单源最短路的,我用了堆优化dijikstra ,复杂度 mlogm,值得拥有!(只不过我在定义优先队列时把greater 打成了 less调了好久 然后我们就求出了$i$到源点的 ... 
- HDU 1142 A Walk Through the Forest(Dijkstra+记忆化搜索)
		题意:看样子很多人都把这题目看错了,以为是求最短路的条数.真正的意思是:假设 A和B 是相连的,当前在 A 处, 如果 A 到终点的最短距离大于 B 到终点的最短距离,则可以从 A 通往 B 处,问满 ... 
- 【UVA11324】 The Largest Clique  (Tarjan+topsort/记忆化搜索)
		UVA11324 The Largest Clique 题目描述 给你一张有向图 \(G\),求一个结点数最大的结点集,使得该结点集中的任意两个结点 \(u\) 和 \(v\) 满足:要么 \(u\) ... 
- 洛谷 P3953 逛公园【spfa+记忆化dfs+bfs】
		spfa预处理出最短路数组dis,然后反向建边bfs出ok[u]表示u能到n点 然后发现有0环的话时候有inf解的,先dfs找0环判断即可 然后dfs,设状态f[u][v]为到u点,还可以跑最短路+v ... 
- Luogu3953 NOIP2017逛公园(最短路+拓扑排序+动态规划)
		跑一遍dij根据最短路DAG进行拓扑排序,按拓扑序dp即可.wa了三发感觉非常凉. #include<iostream> #include<cstdio> #include&l ... 
- 逛公园 [NOIP2017 D1T3] [记忆化搜索]
		Description 策策同学特别喜欢逛公园.公园可以看成一张N个点M条边构成的有向图,且没有自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值,代表策策经过这条边所要花的 ... 
- 【NOIP2017】逛公园 拆点最短路+拓扑(记忆化搜索
		题目描述 策策同学特别喜欢逛公园.公园可以看成一张N个点M条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间. 策 ... 
随机推荐
- semantic-ui 下拉框
			注意:在使用semantic的下拉框的时候,不仅需要引入semantic.css,还要引入semantic.js,最重要的是引入jquery.否则下拉效果不会显示. 并且,jquery必须先于sema ... 
- UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-25: ordinal not in range(128)
			python报错:UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-25: ordinal not in ... 
- docker技术之基本命令
			我们使用基本命令之前,先来普及一下操作中使用的基本概念 镜像 image 容器 container 仓库 repository 镜像 Docker 镜像是一个特殊的文件系统,除了提供容器运 ... 
- Angular 双向数据绑定
			<!DOCTYPE html><html ng-app="myApp"><head lang="en"> <meta ... 
- 将Vue移动端项目打包成手机app---HBuilder
			将移动端页面打包成app 1.使用 HBuilder 直接编译打包 点击左上角 文件>打开目录>选择目录 选择用Webpack打包好的dist文件目录 由于我添加到项目了,所以会显示该项 ... 
- JS学习笔记  等于和包装对象
			严格等于 a===b 首先判断两边数据的类型,若类型不同,返回false. 若类型相同(1.2和1.2,字符串相等指内容和长度都是一样的),返回true null===null undefined== ... 
- php-memcached详解
			一.memcached 简介 在很多场合,我们都会听到 memcached 这个名字,但很多同学只是听过,并没有用过或实际了解过,只知道它是一个很不错的东东.这里简单介绍一下,memcached 是高 ... 
- python之路-列表、元组、range
			一 . 列表 # 列表的定义 列表就是能装对象的对象 在python中用[ ]来描述列表,内部元素用逗号隔开,对数据类型没有要求 索引和切片 lst = ["天龙八部", &quo ... 
- Windows 10 & change DNS
			Windows 10 & change DNS https://www.windowscentral.com/how-change-your-pcs-dns-settings-windows- ... 
- AVL树,红黑树
			AVL树 https://baike.baidu.com/item/AVL%E6%A0%91/10986648 在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高 ... 
