先跑一边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+记忆化搜索)的更多相关文章

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

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

  2. HDU1142 (Dijkstra+记忆化搜索)

    A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Jav ...

  3. Luogu 3953[NOIP2017] 逛公园 堆优化dijkstra + 记忆化搜索

    题解 首先肯定是要求出单源最短路的,我用了堆优化dijikstra ,复杂度 mlogm,值得拥有!(只不过我在定义优先队列时把greater 打成了 less调了好久 然后我们就求出了$i$到源点的 ...

  4. HDU 1142 A Walk Through the Forest(Dijkstra+记忆化搜索)

    题意:看样子很多人都把这题目看错了,以为是求最短路的条数.真正的意思是:假设 A和B 是相连的,当前在 A 处, 如果 A 到终点的最短距离大于 B 到终点的最短距离,则可以从 A 通往 B 处,问满 ...

  5. 【UVA11324】 The Largest Clique (Tarjan+topsort/记忆化搜索)

    UVA11324 The Largest Clique 题目描述 给你一张有向图 \(G\),求一个结点数最大的结点集,使得该结点集中的任意两个结点 \(u\) 和 \(v\) 满足:要么 \(u\) ...

  6. 洛谷 P3953 逛公园【spfa+记忆化dfs+bfs】

    spfa预处理出最短路数组dis,然后反向建边bfs出ok[u]表示u能到n点 然后发现有0环的话时候有inf解的,先dfs找0环判断即可 然后dfs,设状态f[u][v]为到u点,还可以跑最短路+v ...

  7. Luogu3953 NOIP2017逛公园(最短路+拓扑排序+动态规划)

    跑一遍dij根据最短路DAG进行拓扑排序,按拓扑序dp即可.wa了三发感觉非常凉. #include<iostream> #include<cstdio> #include&l ...

  8. 逛公园 [NOIP2017 D1T3] [记忆化搜索]

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

  9. 【NOIP2017】逛公园 拆点最短路+拓扑(记忆化搜索

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

随机推荐

  1. java的static与C#的static的异同

    static static同样可以用在类.方法.变量上面,但是在java和C#中所表示的意思完全不同,我个人的总结是C#中的静态和非静态是有一个明显的分界的,静态的是属于类级别的,而非静态的是属于实例 ...

  2. Velocity中为什么要使用{}来明确标识变量

    原因 比如在页面中,页面中有一个$someonename,此时,Velocity将把someonename作为变量名,若我们程序是想在someone这 个变量的后面紧接着显示name字符,则上面的标签 ...

  3. linux关闭触摸板

    关闭触摸板 sudo modprobe -r psmouse 如果打开触摸板就是: sudo modprobe psmouse

  4. Eclipse打开java文件繁体字

    右键-->properties-->Resource-->Text file encoding, 改成utf-8 .

  5. Junit概述

    Junit ->  java unit.也就是说Junit是xunit家族中的一员. unit   <- unit test case,即单元测试用例. Junit  = java uni ...

  6. InnoDB: Error: Table "mysql"."innodb_table_stats" not found.

    问题:打开mysql错误日志时发现大量的如下错误 Error: Table "mysql"."innodb_table_stats" not found. In ...

  7. 常见IT工具软件总结

    1. 阿里云在线迁移服务 2.智能媒体管理 格式转换 业务域名管理 1. 每个业务有一个英文单词, 1. 每个 git 的命名应该是 chgg-业务英文-种类 2. 例如 chgg-plant-api ...

  8. Nginx简单的负载均衡入门

    nginx是用来管理tomcat的,只管理tomcat,并没有管理具体tomcat里面的项目,这里实现了简单的nginx管理两个tomcat的配置,注意upstream节点应该配置到service节点 ...

  9. Uninstall registry

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

  10. Windows Server2008、IIS7启用CA认证及证书制作完整过程

    1         添加活动目录证书服务 1.1          打开服务器管理器,右键点击角色,选择“添加角色”,在“添加角色向导”窗口左侧面板选择“服务器角色”,然后勾选“Active Dire ...