DP+最短路

两遍最短路判零环

DP转移f[i][j] 到点i的距离比最短路多j时的方案数

 #include<bits/stdc++.h>
using namespace std;
const int N=;
struct node
{
    int to,nex,w;
}e[N],z[N];
int cnt,cnt1,head[],head2[];
int add(int x,int y,int w)
{
    e[++cnt1].to=y;e[cnt1].w=w;e[cnt1].nex=head[x];head[x]=cnt1;
    z[++cnt].to=x;z[cnt].w=w;z[cnt].nex=head2[y];head2[y]=cnt;
}
int f[][];
int d1[],d2[],d[],qq[N<<];
bool v[];int n,m,k,p;
void update(int &a,int b)
{
    a=(a+b)%p;
}
queue<int>q;
void work()
{
    scanf("%d%d%d%d",&n,&m,&k,&p);cnt=,cnt1=;
    memset(head,,sizeof(head));
    memset(head2,,sizeof(head2));
    for(int i=;i<=m;++i)
    {
        int x,y,w;
        scanf("%d%d%d",&x,&y,&w);
        add(x,y,w);
    }
    memset(v,,sizeof(v));memset(d1,0x3f,sizeof(d1));
    q.push();d1[]=;v[]=;
    while(!q.empty())
    {
        int x=q.front();q.pop();v[x]=;
        for(int i=head[x];i;i=e[i].nex)
        {
            int y=e[i].to;
            if(d1[y]>d1[x]+e[i].w)
            {
                d1[y]=d1[x]+e[i].w;
                if(!v[y])
                {
                    q.push(y);v[y]=;
                }
            }
        }
    }
    memset(v,,sizeof(v));memset(d2,0x3f,sizeof(d2));
    q.push(n);d2[n]=;v[n]=;
    while(!q.empty())
    {
        int x=q.front();q.pop();v[x]=;
        for(int i=head2[x];i;i=z[i].nex)
        {
            int y=z[i].to;
            if(d2[y]>d2[x]+z[i].w)
            {
                d2[y]=d2[x]+z[i].w;
                if(!v[y])
                {
                    q.push(y);v[y]=;
                }
            }
        }
    }
   
    int top=;memset(d,,sizeof(d));
    for(int i=;i<=n;++i)
    for(int j=head[i];j;j=e[j].nex)
    {
        if(d1[i]+e[j].w==d1[e[j].to])d[e[j].to]++;
    }
    for(int i=;i<=n;++i)if(!d[i])qq[++top]=i;
    for(int i=;i<=top;++i)
    {
        int x=qq[i];
        for(int j=head[x];j;j=e[j].nex)
        if(d1[x]+e[j].w==d1[e[j].to])
        {
            int y=e[j].to;
            d[y]--;
            if(d[y]==)qq[++top]=y;
        }
    }
    for(int i=;i<=n;++i)
    if(d[i]&&d1[i]+d2[i]<=d1[n]+k)
    {
        puts("-1");return;
    }
    int ans=;
    memset(f,,sizeof(f));
    f[][]=;
    for(int i=;i<=k;++i)
    {
        for(int j=;j<=top;++j)
        for(int u=head[qq[j]];u;u=e[u].nex)
        {
            if(d1[qq[j]]+e[u].w==d1[e[u].to])
            update(f[e[u].to][i],f[qq[j]][i]);
        }
       
        for(int j=;j<=n;++j)
        for(int u=head[j];u;u=e[u].nex)
        {
            if(d1[j]+e[u].w!=d1[e[u].to]&&i+d1[j]-d1[e[u].to]+e[u].w<=k)
            update(f[e[u].to][i+d1[j]-d1[e[u].to]+e[u].w],f[j][i]);
        }
    }
    for(int i=;i<=k;++i)
    update(ans,f[n][i]);
    printf("%d\n",ans);
    return ;
}
int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        work();
    }
    return ;
}

NOIP2017 D1T3逛公园的更多相关文章

  1. [luogu P3953] [noip2017 d1t3] 逛公园

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

  2. NOIP2017 D1T3 逛公园

    发现 \(K\) 很小,不妨设置一个 \(O(NK)\) 的 \(DP\). 发现可行的最短路必须满足是 \(d <= dis <= d + K\). 由逆向思维,则是从某点出发,可以消耗 ...

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

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

  4. 【NOIP2017】逛公园(最短路图,拓扑排序,计数DP)

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

  5. NOIP2017:逛公园

    Sol 发现\(NOIP2017\)还没\(AK\)??? 赶紧改 考场上明明打出了\(DP\),没时间了,没判环,重点是没初始化数组,爆\(0\) \(TAT\) 先最短路,然后\(f[i][j]\ ...

  6. 【NOIP2017】逛公园 最短路+DP

    诶,去年场上不会处理$0$的环,只拿了$60$有点可惜. 我们先不管边边权为$0$的边. 我们先跑一次最短路,令$dis[u]$表示从$1$至$u$的最短路的长度. 那么根据题目的要求,从起点走到$u ...

  7. LOJ2316. 「NOIP2017」逛公园【DP】【最短路】【思维】

    LINK 思路 因为我想到的根本不是网上的普遍做法 所以常数出奇的大,而且做法极其暴力 可以形容是带优化的大模拟 进入正题: 首先一个很显然的思路是如果在合法的路径网络里面存在零环是有无数组解的 然后 ...

  8. 【NOIP2017】逛公园 D1 T3

    记忆化搜索 跑一次反向的最短路求出MinDis(u,n)MinDis(u,n)MinDis(u,n) f[u][k]f[u][k]f[u][k]表示dis(u,n)<=MinDis(u,n)+d ...

  9. 【LOJ2316】「NOIP2017」逛公园

    [题目链接] [点击打开链接] [题目概括] 对给定\(K\),起点\(1\)到终点\(n\)中对长度为\([L,L+K]\)的路径计数. \(L\)为\(1\)到\(n\)的最短路长度. [思路要点 ...

随机推荐

  1. Vue的keep-alive

    Vue的keep-alive: 简答的做下理解 缓存!页面从某一个页面跳转到另一个页面的时候,需要进行一定的缓存,然后这个时候调用的钩子函数是actived,而在第一次加载的时候,created.ac ...

  2. android Timer TimerTask用法笔记

    Android中经常会遇到执行一些周期性定时执行的任务.初学的时候经常会使用Thread.sleep()方法.在android中,有Timer可以专门干这个事情. 先看看Timer.class中都是些 ...

  3. Linux 查看网卡流量【转】

        我的系统式RHEL5.   在linux下,查看网卡流量的方法有很多.下面先记录几个,和他们的大概用法.已被以后之需.   一:iptraf   一个很不错的工具.RHEL5 iso自带有,我 ...

  4. [转载]FFmpeg完美入门[3] - FFmpeg功能及使用说明

    1 ffplay对多媒体的支持能力验证 一.视频3gp 177X144 支持播放,在windows下播放正常,但是在linux下面偶有BUG 如果发现画面无法显示而声音可以播放的情况下可以试着切换全屏 ...

  5. git版本控制系统常见操作总结

    简介 Git是强大的版本控制系统,主要功能是针对代码.配置文件等文本进行版本控制.备份等,同时个人认为还是分发代码的一个不错的方式. 常见用法 #创建远程git仓库 [root@test88 ~]# ...

  6. ASP.NET Core 2.0 MVC 发布部署--------- linux安装.NET CORE SDK具体操作链接以及操作总细节

    具体链接:https://www.microsoft.com/net/learn/get-started/linuxubuntu 如下图:

  7. java基础6 面向对象的详解

    本文知识点(目录): 1.1.万物皆对象    1.2.面向对象的概述    1.3.面向对象(java语言)与面向过程(C语言)对比    1.4.面向过程    1.5.对象    1.6.面向对 ...

  8. 为什么需要学UML建模

    今天在看<设计模式>的时候,看到了许多的UML模型图,案例中作者用极少的代码却能讲清楚讲好设计模式的背景和思想,抽象成一张张的UML图就能很好的review和复盘,这对于在工作中习惯用代码 ...

  9. xpath简单应用

    相对路径与绝对路径: 如果"/"处在XPath表达式开头则表示文档根元素,(表达式中间作为分隔符用以分割每一个步进表达式)如:/messages/message/subject是一 ...

  10. s3cmd : Add a config parameter to enable path-style bucket access 当ceph rgw使用域名时,需要支持 path-style bucket特性

    s3cmd 要是1.6.1 之后的版本 增加配置项:  vi .s3cfg use_path_mode = True 源码参考: cat  /usr/local/lib/python2.7/dist- ...