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. 【Codeforces752D】Santa Claus and a Palindrome [STL]

    Santa Claus and a Palindrome Time Limit: 20 Sec  Memory Limit: 512 MB Description 有k个串,串长都是n,每个串有一个a ...

  2. LintCode之二叉树的最大节点

    分治问题,可以把整棵树看做是由一颗颗只有三个节点组成的小树,一颗树的构成是根节点.左子树.右子树,这样只需要从左子树找出一个最大的节点,从右子树找出一个最大的节点,然后与根节点三个取个最大的,就是最终 ...

  3. vue-loader 调用了cssLoaders方法配置了css加载器属性。

    module: { loaders: [ // 这里也是相应的配置,test就是匹配文件,loader是加载器, { test: /\.vue$/, loader: 'vue' }, { test: ...

  4. Dull Chocolates Gym - 101991D 离散化 前缀和

    题目链接:https://vjudge.net/problem/Gym-101991D 具体思路:首先看数据范围,暴力肯定不可以,可以下离散化,然后先求出离散化后每一个点到(1,1)的符合题目的要求的 ...

  5. 给vim安装YouCompleteMe

    要安装YouCompleteMe ,vim须支持python.看是否支持,可以在vim中:version 查看, 如果python前有+号,就是支持,减号就是不支持. 如果不支持,需要以编译安装方式重 ...

  6. 如何通过掩码计算可用的IP数量

    假设掩码是28,28也就是28个1.本身掩码是255.255.255.255那么转换成二进制也就是 11111111,11111111,11111111,11111111 那么28个1也就是: 111 ...

  7. linux device tree源代码解析--转

    //Based on Linux v3.14 source code Linux设备树机制(Device Tree) 一.描述 ARM Device Tree起源于OpenFirmware (OF), ...

  8. tracert和traceroute使用

    Traceroute提取发 ICMP TTL到期消息设备的IP地址并作域名解析.每次 ,Traceroute都打印出一系列数据,包括所经过的路由设备的域名及 IP地址,三个包每次来回所花时间. 转自 ...

  9. centos7下vi的用法

    vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器是完全相 ...

  10. Java集合里的一些“坑”

    这里主要谈下Java集合在使用中容易被忽略.又容易出现的两个“坑”,一个是集合与数组互相转换,另一个是集合遍历删除.主要通过代码演示. 一.集合与数组互相转换中的“坑” //Test1.java pa ...