zoukankan      html  css  js  c++  java
  • 【NOIP2017】逛公园(最短路图,拓扑排序,计数DP)

    题意:

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

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

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

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

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

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

    n<=1e5,m<=2e5,K<=50,1≤P≤1e9,0≤ci≤1000。

    思路:因为K很小,建立以1为源点的最短路图,在最短路图上进行DP计数

    dp[i][j]表示当前在点i,比最短路线多走j时间的方案数

    在1到N的最短路上可能有环,这样会出现-1的情况,同时还有边长为0的存在,这两个问题都可以使用拓扑排序解决

    对于-1拓扑排序后直接判断

    对于边长为0按照拓扑序进行转移

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<string>
      4 #include<cmath>
      5 #include<iostream>
      6 #include<algorithm>
      7 #include<map>
      8 #include<set>
      9 #include<queue>
     10 #include<vector>
     11 using namespace std;
     12 typedef long long ll;
     13 typedef unsigned int uint;
     14 typedef unsigned long long ull;
     15 typedef pair<int,int> PII;
     16 typedef vector<int> VI;
     17 #define fi first
     18 #define se second
     19 #define MP make_pair
     20 #define N   110000
     21 #define M   210000
     22 #define eps 1e-8
     23 #define pi acos(-1)
     24 priority_queue<pair<int,int> > q;
     25  
     26 int dp[N][51],head[M],vet[M],nxt[M],len[M],head2[M],vet2[M],nxt2[M],len2[M],
     27     dis[N],dis2[N],vis[N],p[N],d[N],tot,tot2;
     28     
     29 void add(int a,int b,int c)
     30 {
     31     nxt[++tot]=head[a];
     32     vet[tot]=b;
     33     len[tot]=c;
     34     head[a]=tot;
     35 }
     36 
     37 void add2(int a,int b,int c)
     38 {
     39     nxt2[++tot2]=head2[a];
     40     vet2[tot2]=b;
     41     len2[tot2]=c;
     42     head2[a]=tot2;
     43 }
     44 
     45 int main()
     46 {
     47     //freopen("uoj331.in","r",stdin);
     48   //  freopen("uoj331.out","w",stdout);
     49     int cas;
     50     scanf("%d",&cas);
     51     for(int v1=1;v1<=cas;v1++)
     52     {
     53         int n,m,K,MOD;
     54         scanf("%d%d%d%d",&n,&m,&K,&MOD);
     55         tot=tot2=0;
     56         memset(head,0,sizeof(head));
     57         memset(head2,0,sizeof(head2));
     58         for(int i=1;i<=m;i++)
     59         {
     60             int x,y,z;
     61             scanf("%d%d%d",&x,&y,&z);
     62             add(x,y,z);
     63             add2(y,x,z);
     64         }
     65         //printf("readend
    "); 
     66         memset(vis,0,sizeof(vis));
     67            memset(dis,0x3f,sizeof(dis));
     68         memset(d,0,sizeof(d));
     69         q.push(MP(0,1)); dis[1]=0;
     70         while(!q.empty())
     71         {
     72             int u=q.top().se; 
     73             q.pop();
     74             if(vis[u]) continue;
     75             vis[u]=1;
     76             int e=head[u];
     77             while(e)
     78             {
     79                 int v=vet[e];
     80                 if(dis[u]+len[e]<dis[v])
     81                 {
     82                     dis[v]=dis[u]+len[e];
     83                     q.push(MP(-dis[v],v));
     84                 }
     85                 e=nxt[e];
     86             }
     87         }
     88         //printf("dijk1end
    ");
     89         memset(vis,0,sizeof(vis));
     90         memset(dis2,0x3f,sizeof(dis2));
     91         q.push(MP(0,n)); dis2[n]=0;
     92         while(!q.empty())
     93         {
     94             int u=q.top().se;
     95             q.pop();
     96             if(vis[u]) continue;
     97             vis[u]=1;
     98             int e=head2[u];
     99             while(e)
    100             {
    101                 int v=vet2[e];
    102                 if(dis2[u]+len2[e]<dis2[v])
    103                 {
    104                     dis2[v]=dis2[u]+len2[e];
    105                     q.push(MP(-dis2[v],v));
    106                 }
    107                 e=nxt2[e];
    108             }
    109         }
    110         //printf("dijk2end
    ");
    111         for(int i=1;i<=n;i++)
    112         {
    113             int e=head[i];
    114             while(e)
    115             {
    116                 int v=vet[e];
    117                 if(dis[i]+len[e]==dis[v]) d[v]++;
    118                 e=nxt[e];
    119             }
    120         }
    121         tot=0;
    122         for(int i=1;i<=n;i++)
    123          if(!d[i]) p[++tot]=i;
    124         //printf("%d
    ",tot);
    125         for(int i=1;i<=tot;i++)
    126         {
    127             int u=p[i];
    128             int e=head[u];
    129             while(e)
    130             {
    131                 int v=vet[e];
    132                 if(dis[u]+len[e]==dis[v])
    133                 {
    134                     d[v]--;
    135                     if(!d[v]) p[++tot]=v;
    136                 }
    137                 e=nxt[e];
    138             }
    139         }
    140         //printf("topoend
    ");
    141         int flag=1;
    142         for(int i=1;i<=n;i++)
    143          if(d[i]&&dis[i]+dis2[i]<=dis[n]+K)
    144          {
    145              printf("-1
    ");
    146              flag=0;
    147              break;
    148          }
    149         if(!flag) continue;
    150         memset(dp,0,sizeof(dp));
    151         dp[1][0]=1;
    152         for(int k=0;k<=K;k++)
    153         {
    154             for(int i=1;i<=tot;i++)
    155             {
    156                 int u=p[i];
    157                 int e=head[u];
    158                 while(e)
    159                 {
    160                     int v=vet[e];
    161                     if(dis[u]+len[e]==dis[v]) dp[v][k]=(dp[v][k]+dp[u][k])%MOD;
    162                     e=nxt[e];
    163                 }
    164             }
    165             
    166             for(int i=1;i<=n;i++)
    167             {
    168                 int e=head[i];
    169                 while(e)
    170                 {
    171                     int v=vet[e];
    172                     int t=k+dis[i]+len[e]-dis[v]; 
    173                      if(dis[i]+len[e]!=dis[v]&&t<=K) dp[v][t]=(dp[v][t]+dp[i][k])%MOD;
    174                     e=nxt[e];
    175                 }
    176             }
    177         }
    178         ll ans=0;
    179         for(int i=0;i<=K;i++) ans=(ans+dp[n][i])%MOD;
    180         printf("%lld
    ",ans);
    181     }
    182     return 0;
    183 }
  • 相关阅读:
    boost库
    DISALLOW_COPY_AND_ASSIGN
    汇编语言入门
    gflags
    Segmentation Fault
    ubuntu16.04_cuda9.0_opencv3.4_cudnn_v7_caffe
    make: aarch64-himix100-linux-gcc: Command not found
    gtest
    glog
    [Go]go语言实战-go版本的supervisord编译安装与运行
  • 原文地址:https://www.cnblogs.com/myx12345/p/9797838.html
Copyright © 2011-2022 走看看