• BZOJ4773: 负环


    n<=300个点的有向图求点数最少的负环。

    先倍增,用floyd找到最少出现负环的走2^k的最短路,把倍增过程中那些图记下来。倍增floyd就跟矩阵快速幂一样的,因为:把floyd当成一次乘法,走一步的图*走一步的图=走两步的图,走两步的图*走两步的图=走四步的图……

    不过有个小问题,走3步出现负环时走四步不一定有,因此初始化时,把邻接矩阵上主对角线都设为0,这样就是“走不超过2^k步时的最短路”,当主对角线出现负数时即这个k是最小的满足走2^k步出现负环的。如果超过log2n即9没出现负环,那这图是没负环的。

    接下来就从k-1枚举到0,每个地图和原地图(主对角线0,其他inf)进行一次“乘法”,如果*完不会出现负环就把原地图*=当前地图,这跟lca的倍增差不多。最后答案+1即可。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stdlib.h>
     4 #include<algorithm>
     5 //#include<iostream>
     6 using namespace std;
     7  
     8 int n,m;
     9 #define maxn 311
    10 typedef int mat[maxn][maxn];
    11 mat mp,f[11],tmp;
    12 const int inf=0x3f3f3f3f;
    13 void init(mat a)
    14 {
    15     for (int i=1;i<=n;i++)
    16         for (int j=1;j<=n;j++)
    17             a[i][j]=inf;
    18 }
    19 void copy(mat b,mat a) {memcpy(b,a,sizeof(mat));}
    20 void mul(mat a,mat b,mat ans)
    21 {
    22     mat tmp;init(tmp);
    23     for (int k=1;k<=n;k++)
    24         for (int i=1;i<=n;i++)
    25             for (int j=1;j<=n;j++)
    26                 tmp[i][j]=min(tmp[i][j],a[i][k]+b[k][j]);
    27     copy(ans,tmp);
    28 }
    29 int x,y,v;
    30 int main()
    31 {
    32     scanf("%d%d",&n,&m);
    33     init(f[0]);
    34     for (int i=1;i<=n;i++) f[0][i][i]=0;
    35     for (int i=1;i<=m;i++)
    36     {
    37         scanf("%d%d%d",&x,&y,&v);
    38         f[0][x][y]=v;
    39     }
    40     int most=1;
    41     for (int &i=most;i<=9;i++)
    42     {
    43         mul(f[i-1],f[i-1],f[i]);bool flag=0;
    44         for (int j=1;j<=n;j++) if (f[i][j][j]<0) flag=1;
    45         if (flag) break;
    46     }
    47     if (most>9) puts("0");
    48     else
    49     {
    50         init(mp);
    51         for (int i=1;i<=n;i++) mp[i][i]=0;
    52         int ans=0;
    53         while (--most>=0)
    54         {
    55             mul(mp,f[most],tmp);bool flag=0;
    56             for (int j=1;j<=n;j++) if (tmp[j][j]<0) flag=1;
    57             if (!flag) ans+=1<<most,copy(mp,tmp);
    58         }
    59         printf("%d
    ",ans+1);
    60     }
    61     return 0;
    62 }
    View Code
  • 相关阅读:
    K8S学习笔记之k8s使用ceph实现动态持久化存储
    Linux学习笔记之Centos7 自定义systemctl服务脚本
    ELK学习笔记之Kibana权限控制和集群监控
    ELK学习笔记之ELK6.0 X-pack设置用户名和密码
    Linux学习笔记之rsync配置
    K8S学习笔记之Pod的Volume emptyDir和hostPath
    不小心删除了某个包的一部分,重新安装方法
    串口数据解析总结
    CMakeLists 链接库相关指令
    google 开源项目阅读计划
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7636520.html
Copyright © 2020-2023  润新知