zoukankan      html  css  js  c++  java
  • 【BZOJ4773】负环 [SPFA][二分]

    负环

    Time Limit: 100 Sec  Memory Limit: 256 MB
    [Submit][Status][Discuss]

    Description

      在忘记考虑负环之后,黎瑟的算法又出错了。对于边带权的有向图 G = (V, E),请找出一个点数最小的环,使得环上的边权和为负数。保证图中不包含重边和自环。

    Input

      第1两个整数n, m,表示图的点数和边数。
      接下来的m行,每<=三个整数ui, vi, wi,表<=有一条从ui到vi,权值为wi的有向边。

    Output

      仅一行一个整数,表示点数最小的环上的点数,若图中不存在负环输出0。

    Sample Input

      3 6
      1 2 -2
      2 1 1
      2 3 -10
      3 2 10
      3 1 -10
      1 3 10

    Sample Output

      2

    HINT

      2 <= n <= 300
      0 <= m <= n^2
      1 <= ui, vi <= n
      |wi| <= 10^4

    Main idea

      给定若干单向边,找出点数最小的负环。

    Solution

      显然直接二分答案,用DfsSPFA限制深搜层数判断是否存在可行负环即可。

    Code

     1 #include<iostream>  
     2 #include<algorithm>  
     3 #include<cstdio>  
     4 #include<cstring>  
     5 #include<cstdlib>  
     6 #include<cmath>  
     7 using namespace std;
     8    
     9 const int ONE = 305;
    10 const int EDG = ONE*ONE; 
    11      
    12 int n,m;
    13 int x,y,z;
    14 int next[EDG],first[EDG],go[EDG],w[EDG],tot;
    15 int vis[ONE],dist[ONE];
    16 int PD;
    17      
    18 int get()
    19 {
    20         int res=1,Q=1;    char c;
    21         while( (c=getchar())<48 || c>57)
    22         if(c=='-')Q=-1;
    23         if(Q) res=c-48; 
    24         while((c=getchar())>=48 && c<=57) 
    25         res=res*10+c-48; 
    26         return res*Q; 
    27 }
    28       
    29 void Add(int u,int v,int z)
    30 {
    31         next[++tot]=first[u];    first[u]=tot;    go[tot]=v;    w[tot]=z;
    32 }
    33      
    34 void Spfa(int u,int T,int Limit)
    35 {
    36         if(PD) return;
    37         for(int e=first[u];e;e=next[e])
    38         {
    39             int v = go[e];
    40             if(dist[u]+w[e] <= dist[v])
    41             {
    42                 if(vis[v]) {PD = 1; return;}
    43                 if(T==Limit) return;
    44                 dist[v] = dist[u] + w[e];
    45                 vis[v] = 1;
    46                 Spfa(v,T+1,Limit);
    47                 vis[v] = 0;
    48             }
    49         }
    50 }
    51      
    52 int Check(int Limit)
    53 {
    54         PD = 0;
    55         for(int i=1;i<=n;i++)
    56         {
    57             memset(vis,0,sizeof(vis));  vis[i] = 1;
    58             memset(dist,0,sizeof(dist));
    59             Spfa(i,1,Limit);
    60             if(PD) return 1;
    61         }
    62         return 0;
    63 }
    64      
    65 int main()
    66 {
    67         n=get();    m=get();
    68         for(int i=1;i<=m;i++)
    69         {
    70             x=get();    y=get();    z=get();
    71             Add(x,y,z);
    72         }
    73              
    74         if(!Check(n)) {printf("0"); exit(0);}
    75              
    76         int l=1, r=n;
    77         while(l < r-1)
    78         {
    79             int mid = l+r>>1;
    80             if(Check(mid)) r = mid;
    81             else l = mid;
    82         }
    83           
    84         if(Check(l)) printf("%d",l);
    85         else printf("%d",r);
    86 }
    87 
    View Code
  • 相关阅读:
    2018ACM上海大都会赛 F Color it【基础的扫描线】
    2018大都会赛 A Fruit Ninja【随机数】
    两个数互质的概率
    【shell脚本学习-3】
    【mysql学习-1】
    【HCNE题型自我考究】
    【为系统营造的一个安全的环境】
    【nginx下对服务器脚本php的支持】
    【linux基于Postfix和Dovecot邮件系统的搭建】
    不同状态的动态路由协议对比
  • 原文地址:https://www.cnblogs.com/BearChild/p/6624302.html
Copyright © 2011-2022 走看看