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. 20155117王震宇 2006-2007-2 《Java程序设计》第二周学习总结

    学号 2006-2007-2 <Java程序设计>第X周学习总结 教材学习内容总结 学习一门语言首先要熟悉基础的语法,注意不要和之前学过的语言知识混淆. java严格区分大小写. 教材学习 ...

  2. How to reset XiaoMi bluetooth headphone Youth edition.

    To reset the speaker 1. Long press the phone call button to shut off the speaker 2. Connect the char ...

  3. 2、Web基本介绍及Html语法介绍

    1.1 Web基本介绍 1.web就是world wide web的缩写.称之为全球广域网,俗称www.2.我们可以将web理解为就是当前的一种互联网.对于我们来说更多的就是网站服务.3.网站我们可以 ...

  4. gitlab使用 —— 多人协同工作(重要技能)

    gitlab使用 —— 多人协同工作(重要技能) 学习链接: http://herry2013git.blog.163.com/blog/static/219568011201341111240751 ...

  5. spring boot 自定义属性覆盖application文件属性

    参考 Spring boot源码分析-ApplicationListener应用环境: https://blog.csdn.net/jamet/article/details/78042486 加载a ...

  6. numpy 简介

    .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px so ...

  7. ubuntu12.04 svn ssl错误

    1,ubuntu12.04 svn ssl错误提示: OPTIONS of '<url>': SSL handshake failed: SSL error: Key usage viol ...

  8. MySQL 视图、触发器、函数、存储过程

    1. 视图 1.1 什么是视图 通俗来讲,视图就是一条 select 语句执行后返回的结果集.所有我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上. 1.2 视图的特性 视图是对若干张基 ...

  9. Java web项目中新建maven项目出现的问题

    1.首先新建maven项目,新建Maven时出现了版本问题,报错 第一个错误:jdk版本与project facets不匹配(大概是这样,忘记截图了),那么解决办法是: 在项目右击--->Pro ...

  10. Linux 硬盘挂载方法

    linux 硬盘分区,分区,删除分区,格式化,挂载,卸载笔记 硬盘挂载操作工作步骤: 1.先查看目前机器上有几块硬盘,查看命令有两种: 命令1:# fdisk –l 命令2:# dmesg | gre ...