zoukankan      html  css  js  c++  java
  • NOIP2017逛公园(dp+最短路)

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

    策策每天都会去逛公园,他总是从1号点进去,从N号点出来。

    策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间。如果1号点 到N号点的最短路长为d,那么策策只会喜欢长度不超过d+K的路线。

    策策同学想知道总共有多少条满足条件的路线,你能帮帮它吗?

    为避免输出过大,答案对P取模。

    如果有无穷多条合法的路线,请输出−1

    Solution

    看这像个分层图(其实也是分层图2333),首先一眼看到最短路计数,30pts到手。。

    我们先把最短路DAG搞出来,拓扑一遍。

    什么情况有无穷多解,有0环,我们拓扑完之后,如果还有点有入度,就是无解。

    考虑到转移是和k相关的,而且是从小往大转移的,所以我们在枚举k之后,对于i->i转移的转移,我们按照拓扑序进行dp,对于i->i+k的转移,按照分层图的顺序转移就可以了。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define N 100002
    #define M 200002
    #define mm make_pair
    using namespace std;
    queue<int>q1;
    priority_queue<pair<int,int> >q; 
    int dis[N],du[N],head[N],tot,n,t[N],tt,T,m,k,p,dp[N][52],ans,tttt;
    bool vis[N];
    struct fdd{
        int n,to,l;
    }e[M];
    inline void unit(){
        tot=0;
        memset(head,0,sizeof(head));
        memset(dp,0,sizeof(dp));tt=0;tttt=0;
        memset(du,0,sizeof(du));
    }
    inline void add(int u,int v,int l){
        e[++tot].n=head[u];
        e[tot].to=v;e[tot].l=l;
        head[u]=tot;
    } 
    inline void dij(int s){
        memset(dis,0x3f,sizeof(dis));
        memset(vis,0,sizeof(vis));
        dis[s]=0;q.push(mm(0,s));
        while(!q.empty()){
            int u=q.top().second;q.pop();
            if(vis[u])continue;vis[u]=1;
            for(int i=head[u];i;i=e[i].n){
                int v=e[i].to;
                if(dis[v]>dis[u]+e[i].l){
                    dis[v]=dis[u]+e[i].l;
                    q.push(mm(-dis[v],v));
                }
            }
        }
    }
    inline void topo(){
        for(int i=1;i<=n;++i)if(!du[i])q1.push(i);
        while(!q1.empty()){
            int u=q1.front();q1.pop();t[++tt]=u;
            for(int i=head[u];i;i=e[i].n)if(dis[e[i].to]==dis[u]+e[i].l){
                int v=e[i].to;
                if(!--du[v])q1.push(v);
            }
        }
        for(int i=1;i<=n;++i)if(du[i])tttt=1;
    }
    inline int rd(){
        int x=0;char c=getchar();
        while(!isdigit(c))c=getchar();
        while(isdigit(c)){
            x=(x<<1)+(x<<3)+(c^48);
            c=getchar();
        }
        return x;
    }
    int main(){
        T=rd();
        while(T--){
            unit();
            int u,v,w;
            n=rd();m=rd();k=rd();p=rd();
            for(int i=1;i<=m;++i){
                u=rd();v=rd();w=rd();add(u,v,w);
            }
            dij(1);
            memset(vis,0,sizeof(vis));
            for(int u=1;u<=n;++u){
                for(int i=head[u];i;i=e[i].n){
                    int v=e[i].to;
                    if(dis[u]+e[i].l==dis[v])du[v]++;
                }
            }
            topo();
            if(tttt){
                printf("-1
    ");
                continue;
            }
            dp[1][0]=1;
            for(int i=0;i<=k;++i){
                for(u=1;u<=tt;++u)
                  for(int j=head[t[u]];j;j=e[j].n)if(dis[t[u]]+e[j].l==dis[e[j].to]){
                      int v=e[j].to;
                      (dp[v][i]+=dp[t[u]][i])%=p;
                  }
                for(int u=1;u<=n;++u)
                  for(int j=head[u];j;j=e[j].n)if(dis[u]+e[j].l!=dis[e[j].to]){
                      int v=e[j].to;
                      int kk=dis[u]-dis[v]+e[j].l+i;
                      if(kk<=k)(dp[v][kk]+=dp[u][i])%=p;
                  }
            }
            ans=0;
            for(int i=0;i<=k;++i)(ans+=dp[n][i])%=p;
            printf("%d
    ",ans);
        }
        return 0; 
    }

     

     

  • 相关阅读:
    spring的工厂类
    spring的基于XML方式的属性注入
    github上传大于100M的文件报错
    fatal: HttpRequestException encountered
    VAR 学习笔记3
    You are my great sunshine
    warning: LF will be replaced by CRLF in
    术语词汇
    XGBoost学习笔记2
    四大基本算法思想
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9582824.html
Copyright © 2011-2022 走看看