noip2017d1t3
其实是参考洛谷上某篇题解的思路;
先求出两个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的更多相关文章
- 并不对劲的noip2017d1t3
因为A掉了d1t1,十分开心,把d1t3的代码调出来了. 一般情况下,noip每一天总有一道dp题,然而d1前两道题都不是,再看看第三题的数据范围,就能大概猜出是dp了. 这道题和最短路计数看上去很像 ...
- noip2017D1T3逛公园(拓扑图上dp,记忆化搜索)
QWQ前几天才刚刚把这个D1T3写完 看着题解理解了很久,果然我还是太菜了QAQ 题目大意就是 给你一个n个点,m条边的图,保证1能到达n,求从1到n的 (设1到n的最短路长度是d)路径长度在[d,d ...
- 洛谷P3953逛公园
题目 作为\(NOIp2017D1T3\) 这个题还是很良心的,至少相对于\(NOIp2018\)来说,希望\(NOIp2019\)不会这么坑吧. 这个题可以作为记忆化搜索的进阶题了,做这个题的方法也 ...
随机推荐
- 【gRPC使用问题2】按照问题1操作生成出来的代码,import的proto内定义的message未生成出来
1.问题 其实元数据proto里是有定义message,但是 这个message的定义是在另一个 proto文件内,被 api.proto导入,事实上 我是对 api.proto 进行命令行生成代码的 ...
- 制作根文件系统之内核如何启动init进程
start_kernel其实也是内核的一个进程,它占用了进程号0,start_kernel的内容简写如下: asmlinkage void __init start_kernel(void) //内核 ...
- iOS.PrototypeTools
1. iPhone/iPad 原型工具 http://giveabrief.com/ 2. proto.io https://proto.io/ 3. Origami http://facebook. ...
- Android.Tools.Summary
Android平台上工具的总结 每个工具的详细使用和深入理解参考每个工具相关的blog. 1. Android SDK中提供的工具 http://developer.android.com/tools ...
- 添加exe为windows service服务
[方法一] 一.介绍 srvany.exe是Microsoft Windows Resource Kits工具集的一个实用小工具,用于将EXE程序作为Windows服务运行.srvany是其注册程序的 ...
- windows下Git的使用教程(github)
这表文章主要是用命令操作: 使用可视化软件操作:https://www.cnblogs.com/mswyf/p/9261859.html 一.下载安装Git Bash 下载安装:https://www ...
- 重启ngix失败
问题如下: 解决办法:杀死nginx进程,再重启 .查找nginx主进程:ps -ef|grep nginx .杀死进程:kill - .启动:cd /usr/sbin./nginx -t
- bootstrap 坑
1. 表格内存出不来,也不报错 .. 值是对的.. 原因是 table 中必须有属性 data-toggle="table" <table id="My ...
- 【NIFI】 开发自定义Nifi Processor
本例需要基础知识:[NIFI] Apache NiFI 安装及简单的使用 Nifi不光可以使用自带的Processor,还可以自定义Processor.本例简单介绍开发一个Processor 开发 1 ...
- MySQL把本地数据库上传到linux
今天是要导入数据库到linux系统 先用Navicat把sql导出,然后登陆到linux去执行 登陆mysql: mysql -uroot -p123456 创建数据库:create database ...