zoukankan      html  css  js  c++  java
  • 【NOIP2017】逛公园 最短路+DP

    诶,去年场上不会处理$0$的环,只拿了$60$有点可惜。

    我们先不管边边权为$0$的边。

    我们先跑一次最短路,令$dis[u]$表示从$1$至$u$的最短路的长度。

    那么根据题目的要求,从起点走到$u$号点的路径长度只可能在区间$[dis[u],dis[u]+k]$中。

    令$f[i][j]$表示当前从起点走到$i$,行走的路程为$dis[i]+j$的方案数。

    不妨发现这个东西可以通过类似分层图最短路的方式进行更新,然后就直接更新就行了。

    然而这一题中有部分点存在边权为$0$的边,一旦走入一个$0$环的话采用上述的方法会$TLE$。

    于是我们把上面的通过分层图最短路的更新方式,更换为记忆化搜索,我们在当前搜索的路径上打上标记,然后若走到之前标记过的点,那么直接输出$-1$退出即可。这种方式可以有效避免将无需经过的零环纳入考虑范围内。

    (可能是个人写法的原因),经过$1$的零环需要特判,直接在最短路里判掉就好了。

    然后就没了。时间复杂度:$O(mk+m log n)$。

     1 #include<bits/stdc++.h>
     2 #define M 100005
     3 using namespace std;
     4 
     5 struct edge{int u,v,next;}e[M*4]={0}; int head[M]={0},head1[M]={0},use=0;
     6 void add(int x,int y,int z){use++;e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use;}
     7 void add1(int x,int y,int z){use++;e[use].u=y;e[use].v=z;e[use].next=head1[x];head1[x]=use;}
     8 int n,m,k,MOD;
     9 
    10 struct node{
    11     int x,dis;
    12     node(){x=dis=0;}
    13     node(int xx,int ddis){x=xx; dis=ddis;}
    14     friend bool operator <(node a,node b){return a.dis>b.dis;}
    15 }a[M];
    16 priority_queue<node> q;
    17 int vis[M]={0},dis[M]={0},v[M][52]={0},f[M][52]={0},in[M][52]={0};
    18 int dij(){
    19     q.push(node(1,0));
    20     while(!q.empty()){
    21         node U=q.top(); q.pop();
    22         int u=U.x;
    23         if(vis[u]) continue;
    24         vis[u]=1; dis[u]=U.dis;
    25         for(int i=head[u];i;i=e[i].next){ 
    26             if(dis[u]+e[i].v==0&&e[i].u==1) return 0;
    27             if(!vis[e[i].u]) q.push(node(e[i].u,dis[u]+e[i].v));
    28         }
    29     }
    30     return 1;
    31 }
    32 
    33 int dfs(int x,int p){
    34     if(f[x][p]!=-1) return f[x][p];
    35     if(in[x][p]) return -233;
    36     int res=0; in[x][p]=1;
    37     for(int i=head1[x];i;i=e[i].next){
    38         int v=dis[x]-dis[e[i].u]+p-e[i].v;
    39         if(0<=v&&v<=k){
    40             int now=dfs(e[i].u,v);
    41             if(now==-233) return -233;
    42             res=(res+now)%MOD;
    43         }
    44     }
    45     f[x][p]=res; in[x][p]=0;
    46     return res;
    47 }
    48 
    49 int Main(){
    50     memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); 
    51     memset(f,-1,sizeof(f)); memset(e,0,sizeof(e));
    52     memset(head,0,sizeof(head)); memset(head1,0,sizeof(head1)); use=0;
    53     memset(in,0,sizeof(in));
    54     memset(v,0,sizeof(v));
    55     scanf("%d%d%d%d",&n,&m,&k,&MOD);
    56     for(int i=1;i<=m;i++){
    57         int x,y,z; scanf("%d%d%d",&x,&y,&z);
    58         add(x,y,z);
    59         add1(y,x,z);
    60     }
    61     if(dij()==0){printf("-1
    "); return 0;}
    62     int ans=0; f[1][0]=1;
    63     for(int i=0;i<=k;i++){
    64         int now=dfs(n,i);
    65         if(now==-233){
    66             printf("-1
    ");
    67             return 0;
    68         }
    69         ans=(ans+now)%MOD;
    70     }
    71     printf("%d
    ",ans);
    72 }
    73 
    74 int main(){
    75     int cas; cin>>cas;
    76     while(cas--) Main();
    77 }
  • 相关阅读:
    Android code wiki
    Android 屏蔽ScrollView滑动操作
    Android PorterDuff.Mode
    微信小程序开发——小程序分享转发
    支付宝小程序开发之与微信小程序不同的地方
    微信小程序快速移植支付宝小程序
    微信小程序开发——小程序API获取用户位置及异常流处理完整示例
    微信小程序开发——开发者工具中素材管理功能使用的注意事项
    js数组排序实用方法集锦
    chrome谷歌浏览器常用快捷键搜集整理
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/9769356.html
Copyright © 2011-2022 走看看