其实是参考洛谷上某篇题解的思路;

先求出两个dis数组表示从1走和从n走的最短路;

转移方程:dp[v][dis1[u]-dis1[v]+w+j]+=dp[u][j];

转移顺序要注意一下呢,肯定是先枚举第二维;

dis1[u]-dis1[v]+w+j>=j;

因为有等号,即有同层之间的转移,第一维也不能随便枚举;

如果没有0边,我们可以考虑按dis1从小到大枚举,和dijkstra很像,可以保证更新顺序是对的;

有了零边就要考虑连续好几个零边之间的转移,这个可以把0边挑出来拓扑排序;

关于-1的判断,把零边挑出来之后是可以知道那些点是在零环中的,再看一下经过这个点的路径有没有满足条件的就好了。

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=;
const ll inf=1e12;
ll dp[maxn][],dis[maxn][];
struct edg{
int nex,to;
ll w;
}e[maxn*][];
struct node{
int id;
ll dis;
bool operator<(const node&a)const{
return dis>a.dis;
}
}A,B;
int s,flag,head,tail,t1,t2,vis[maxn],last[maxn][],T,n,m,k,p,x,y,qq[maxn];
int h[maxn],pre[maxn*],other[maxn*],t3,du[maxn],tot,in[maxn];
ll z;
priority_queue<node>q;
void add3(int x,int y){++t3;pre[t3]=h[x];h[x]=t3;other[t3]=y;}
void add1(int x,int y,ll z){++t1;e[t1][].nex=last[x][];last[x][]=t1;e[t1][].to=y;e[t1][].w=z;}
void add2(int x,int y,ll z){++t2;e[t2][].nex=last[x][];last[x][]=t2;e[t2][].to=y;e[t2][].w=z;}
void dijkstra(int lei){
//lei=0,1为起点,lei=1,n为起点;
while(!q.empty())q.pop();
memset(vis,,sizeof(vis));
for(int i=;i<=n;++i)dis[i][lei]=inf;
if(!lei)s=;else s=n;
dis[s][lei]=;
A.id=s;A.dis=;q.push(A);
while(!q.empty()){
B=q.top();q.pop();
if(vis[B.id])continue;
vis[B.id]=;
for(int i=last[B.id][lei];i;i=e[i][lei].nex){
int v=e[i][lei].to;
if(vis[v])continue;
if(dis[v][lei]>dis[B.id][lei]+e[i][lei].w){
dis[v][lei]=dis[B.id][lei]+e[i][lei].w;
A.id=v;A.dis=dis[v][lei];
q.push(A);
}
}
}
}
struct hehe{
ll dis;
int id,u;
bool operator<(const hehe&a)const{
if(dis==a.dis)return id<a.id;
return dis<a.dis;
}
}lj[maxn];
void tp(){
for(int i=;i<=n;++i){
lj[i].dis=inf;
lj[i].id=;
}
flag=;
head=tail=;
for(int i=;i<=n;++i)if(in[i]&&!du[i]){
qq[++tail]=i;lj[i].id=tail;
}
while(head<tail){
int u=qq[++head];
for(int i=h[u];i;i=pre[i]){
int v=other[i];
du[v]--;
if(!du[v]){qq[++tail]=v;lj[v].id=tail;}
}
}
for(int i=;i<=n;++i){
if(in[i]&&du[i]){
if(dis[i][]+dis[i][]<=dis[n][]+k){
flag=;
}
}
}
}
int main(){
cin>>T;
while(T--){
scanf("%d%d%d%d",&n,&m,&k,&p);
t1=t2=t3=;
memset(last,,sizeof(last));
memset(du,,sizeof(du));
memset(in,,sizeof(in));
memset(dp,,sizeof(dp));
memset(h,,sizeof(h));
for(int i=;i<=m;++i){
scanf("%d%d%lld",&x,&y,&z);
add1(x,y,z);add2(y,x,z);
if(!z){add3(x,y);du[y]++;in[x]=in[y]=;}
}
dijkstra();
dijkstra();
tp();
if(!flag){puts("-1");continue;}
else{
for(int i=;i<=n;++i){
lj[i].dis=dis[i][];
lj[i].u=i;
}
sort(lj+,lj+n+);
dp[][]=;
for(int j=;j<=k;++j)
for(int i=;i<=n;++i)
{
int u=lj[i].u;
for(int l=last[u][];l;l=e[l][].nex){
int v=e[l][].to;
if(dis[u][]-dis[v][]+e[l][].w+j<=k){
dp[v][dis[u][]-dis[v][]+e[l][].w+j]+=dp[u][j];
if(dp[v][dis[u][]-dis[v][]+e[l][].w+j]>=p)dp[v][dis[u][]-dis[v][]+e[l][].w+j]-=p;
}
}
}
ll ans=;
for(int i=;i<=k;++i){
ans+=dp[n][i];
if(ans>=p)ans-=p;
}
printf("%lld\n",ans);
}
}
//system("pause");
return ;
}

代码

noip2017d1t3的更多相关文章

  1. 并不对劲的noip2017d1t3

    因为A掉了d1t1,十分开心,把d1t3的代码调出来了. 一般情况下,noip每一天总有一道dp题,然而d1前两道题都不是,再看看第三题的数据范围,就能大概猜出是dp了. 这道题和最短路计数看上去很像 ...

  2. noip2017D1T3逛公园(拓扑图上dp,记忆化搜索)

    QWQ前几天才刚刚把这个D1T3写完 看着题解理解了很久,果然我还是太菜了QAQ 题目大意就是 给你一个n个点,m条边的图,保证1能到达n,求从1到n的 (设1到n的最短路长度是d)路径长度在[d,d ...

  3. 洛谷P3953逛公园

    题目 作为\(NOIp2017D1T3\) 这个题还是很良心的,至少相对于\(NOIp2018\)来说,希望\(NOIp2019\)不会这么坑吧. 这个题可以作为记忆化搜索的进阶题了,做这个题的方法也 ...

随机推荐

  1. c# 多个事件公用一个相应方法判断事件来源

    假设下边的相应方法有多个事件共同使用.根据事件的sender 判断来源,做相应的处理 假设事件来源DataManSystem;private void OnSystemConnected(object ...

  2. PHP 异步使用swoole的可行性测试

    PHP的异步.并行.高性能网络通信引擎swoole框架,在一开始我就比较注意,原因无他,php在swoole未出的情况下在多线程调度上确实算得上没有较好的解决方案. 我以系统的注册流程举例,在比较复杂 ...

  3. Android.PublishApplication

    发布应用 3. 为App签名 Android 要求App在安装前,需要使用证书(certificate)来进行数字签名(be digitally signed). Android 用证书来标识一个Ap ...

  4. Python.Books

    Flask 1. Flask Web Development Miguel Grinberg April 2014 2. Flask Framework Cookbook Shalabh Aggarw ...

  5. java.lang.NoClassDefFoundError: org/apache/ibatis/cursor/Cursor

    因为mybatis的版本和mybatis-spring的版本不兼容导致的,解决方法:mybatis的3.4.0及以上版本用mybatis-spring1.3.0及以上版本:mybatis的3.4.0以 ...

  6. h5 微信分享朋友和朋友圈

    生成JS-SDK权限验证签名 实现发送给朋友和分享到朋友圈时内容参数自定义 一.微信JS-SDK 1. 获得Access Token access token的获得方法在前面有介绍,详情见 微信公众平 ...

  7. a label can only be part of statement and a declaratioin is not a statement

    参考资料: https://stackoverflow.com/questions/18496282/why-do-i-get-a-label-can-only-be-part-of-a-statem ...

  8. [AI]神经网络章2 神经网络中反向传播与梯度下降的基本概念

    反向传播和梯度下降这两个词,第一眼看上去似懂非懂,不明觉厉.这两个概念是整个神经网络中的重要组成部分,是和误差函数/损失函数的概念分不开的. 神经网络训练的最基本的思想就是:先“蒙”一个结果,我们叫预 ...

  9. python入门之字典

    1.字典的基本特征: key-value结构 key唯一,必须为不可变数据类型 value可以不唯一 无序 查找速度快 2.创建一个字典: info={“gaohui”:"IT", ...

  10. zookeeper集群的搭建(三台相同)

    查看jdk java -version 卸载自带jdk rpm -qa|grep java rpm -e --nodeps tzdata-java-2015e-1.el6.noarch rpm -e ...