• 负环 BZOJ 4773


    负环

    【问题描述】

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

    【输入格式】

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

    【输出格式】

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

    【样例输入】

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

    【样例输出】

    2

    【数据范围】

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

    题解:

    考虑二分最小点数,用 Floyed (用倍增来限制步数)检验答案的范围区间

    那么将二分过程化为倍增的过程,可行时不断缩小答案,否则继承当前答案

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<iostream>
     6 #include<algorithm>
     7 using namespace std;
     8 const int maxn = 301;
     9 const int logn = 6;
    10 inline int Get()
    11 {
    12     int x;
    13     char c;
    14     bool o = false;
    15     while((c = getchar()) < '0' || c > '9')
    16         if(c == '-') o = true;
    17     x = c - '0';
    18     while((c = getchar()) >= '0' && c <= '9')
    19         x = x * 10 + c - '0';
    20     return (o) ? -x : x;
    21 }
    22 int n, m;
    23 int f[maxn][maxn][logn + 1], g[maxn][maxn], s[maxn][maxn];
    24 inline void Clear()
    25 {
    26     memset(f, 127 / 2, sizeof(f));
    27     for(int k = 0; k <= logn; ++k)
    28         for(int i = 1; i <= n; ++i)
    29             f[i][i][k] = 0;
    30     memset(s, 127 / 2, sizeof(s));
    31     for(int i = 1; i <= n; ++i) s[i][i] = 0;
    32 }
    33 int main()
    34 {
    35     n = Get(), m = Get();
    36     Clear();
    37     for(int i = 1; i <= m; ++i)
    38     {
    39         int x = Get(), y = Get(), z = Get();
    40         f[x][y][0] = z;
    41     }
    42     for(int l = 1; l <= logn; ++l)
    43         for(int i = 1; i <= n; ++i)
    44             for(int j = 1; j <= n; ++j)
    45                 for(int k = 1; k <= n; ++k)
    46                     f[i][j][l] = min(f[i][j][l], f[i][k][l - 1] + f[k][j][l - 1]);
    47     int ans = 1;
    48     for(int l = logn; l >= 0; --l)
    49     {
    50         memcpy(g, s, sizeof(g));
    51         for(int i = 1; i <= n; ++i)
    52             for(int j = 1; j <= n; ++j)
    53                 for(int k = 1; k <= n; ++k)
    54                     s[i][j] = min(s[i][j], g[i][k] + f[k][j][l]);
    55         bool flag = false;
    56         for(int i = 1; i <= n; ++i)
    57             if(s[i][i] < 0)
    58             {
    59                 flag = true;
    60                 break;
    61             }
    62         if(flag) memcpy(s, g, sizeof(s));
    63         else ans += (1 << l);
    64     }
    65     if(ans > n) printf("0
    ");
    66     else printf("%d
    ", ans);
    67 }
  • 相关阅读:
    07: mysql锁和事物隔离
    06: mysql索引查找原理及调优
    06: 字典、顺序表、列表、hash树 实现原理
    05:树结构
    02:MongoDB操作
    01:MongoDB基础
    02: CMDB设计思路
    二级制包安装Tomcat 与 RPM包安装Tomcat
    Docker的volume机制实现容器数据的持久性存储
    配置docker的私有仓库
  • 原文地址:https://www.cnblogs.com/lytccc/p/6616625.html
Copyright © 2020-2023  润新知