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; 
    }

     

     

  • 相关阅读:
    118/119. Pascal's Triangle/II
    160. Intersection of Two Linked Lists
    168. Excel Sheet Column Title
    167. Two Sum II
    172. Factorial Trailing Zeroes
    169. Majority Element
    189. Rotate Array
    202. Happy Number
    204. Count Primes
    MVC之Model元数据
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9582824.html
Copyright © 2011-2022 走看看