• 递归型SPFA+二分答案 || 负环 || BZOJ 4773


    题解:

    基本思路是二分答案,每次用Dfs型SPFA验证该答案是否合法。

    一点细节我注释在代码里了。

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 inline int rd(){
     5     int x=0,f=1; char c=getchar();
     6     while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
     7     while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
     8     return f*x;
     9 }
    10 const int maxn=305,maxm=305*305,inf=(1<<30)-5;
    11 int N,M,edge_head[maxn],num_edge=0,u,v,w,Dis[maxn];
    12 bool vis[maxn],flag;
    13 struct Edge{ int to,nx,dis; }edge[maxm];
    14 inline void Add_edge(int from,int to,int dis){
    15     edge[++num_edge].nx=edge_head[from];
    16     edge[num_edge].to=to;
    17     edge[num_edge].dis=dis;
    18     edge_head[from]=num_edge;
    19     return;
    20 }
    21 inline void SPFA(int x,int now,int Limit){
    22 //判断是否存在当前位于x,现在已经用了now个点,点数不超过Limit的负环
    23     if(flag) return;
    24     for(int i=edge_head[x];i;i=edge[i].nx){
    25         int y=edge[i].to;
    26         if(Dis[y]>=Dis[x]+edge[i].dis){
    27             if(vis[y]){
    28                 flag=1;
    29                 return;
    30             } 
    31             else if(now+1<=Limit){
    32                 vis[y]=1;
    33                 Dis[y]=Dis[x]+edge[i].dis;
    34                 SPFA(y,now+1,Limit);
    35                 vis[y]=0;
    36                 //这里的Dis[y]不用回溯,其实是一种剪枝 
    37             }
    38         }
    39     }
    40     return;
    41 }
    42 int main(){
    43     N=rd(); M=rd();
    44     for(int i=1;i<=M;i++){
    45         u=rd(); v=rd(); w=rd();
    46         Add_edge(u,v,w);
    47     }
    48     
    49     flag=0;
    50     for(int i=1;i<=N;i++){    
    51         memset(vis,0,sizeof(vis));
    52         memset(Dis,0,sizeof(Dis));
    53         vis[i]=1;
    54         SPFA(i,1,N);
    55         if(flag) break;
    56     }
    57     if(flag==0){
    58         printf("0
    ");
    59         return 0;
    60     }
    61     
    62     int l=2,r=N;
    63     while(l<=r){
    64         int mid=(l+r)>>1;
    65         flag=0;
    66         for(int i=1;i<=N;i++){                
    67             memset(vis,0,sizeof(vis));
    68             memset(Dis,0,sizeof(Dis));
    69             vis[i]=1;
    70             SPFA(i,1,mid);
    71             if(flag){
    72                 r=mid-1;
    73                 break;
    74             }
    75         }
    76         if(!flag) l=mid+1;
    77     }
    78     printf("%d
    ",l);
    79     return 0;
    80 }
    View Code

    By:AlenaNuna

  • 相关阅读:
    文件处理
    字符编码
    基本数据类型及内置方法
    python语法入门之流程控制
    python语法入门之基本数据类型
    python语法入门之用户交互、运算符
    编程语言与Python介绍
    计算机核心基础
    图片验证码推导逻辑,Image.new,ImageDraw, ImageFont.truetype的用法
    VUEday01
  • 原文地址:https://www.cnblogs.com/AlenaNuna/p/11695080.html
Copyright © 2020-2023  润新知