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

先求出两个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. Vue 局部组件和全局组件的使用

    <template> <div id="app"> <!--<img alt="Vue logo" src="./ ...

  2. 11.1JS笔记

    1.js的数据类型分为基本和引用,基本(string.undefined.null.number,boolean),引用(object-->array.function.json等) 2.基本数 ...

  3. C++中的npos,size_t,size_type

    string类提供了6种查找函数,每种函数以不同形式find命名,这些操作全都返回string::size_type类型的值,以下标形式标记查找匹配所发生的位置,或返回一个名为string::npos ...

  4. hdu 5129 (枚举) The E-pang Palace

    题目;http://acm.hdu.edu.cn/showproblem.php?pid=5128. 给你n个点,问能否组成两个不相交的与坐标轴平行的矩形,能就输出两矩形的面积和,不能就输出一个字符串 ...

  5. linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)

      IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...

  6. nodejs buffer 内存泄漏问题

    摘自<Node.js 高级编程> var buffer = new Buffer("this is the content of my buffer"); var sm ...

  7. Python数据库工具类MySQLdb使用

    MySQLdb模块用于连接mysql数据库. 基本操作 # -*- coding: utf-8 -*-       #mysqldb       import time, MySQLdb       ...

  8. Lazarus IOCP 移植

    delphi下面有一个高性能IOCP库,是俄国人写的,在下将其移植到了lazarus下面, lazarus 版本 1.0.12 ,需要的下载 和indy相比较,indy开发的一个web服务器,cpu占 ...

  9. [RF] 安装好Robot Framework之后怎样让启动的界面后面不带命令行窗口,且图片以机器人显示

    安装好Robot Framework之后,通过 C:\Python27\Scripts\ride.py 启动时会带上一个命令行窗口: 怎样让启动的界面后面不带这个命令行窗口,且图片以机器人显示? 方法 ...

  10. IOS初级:NSUserDefaults

    NSUserDefaults(偏好设置),一个APP对应一个偏好设置 保存/新增数据 //存储数据 NSUserDefaults *defaults = [NSUserDefaults standar ...