BZOJ_4773_负环_倍增弗洛伊德

BZOJ_4773_负环

Description

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

环上的边权和为负数。保证图中不包含重边和自环。

Input

第1两个整数n, m,表示图的点数和边数。

接下来的m行,每<=三个整数ui, vi, wi,表<=有一条从ui到vi,权值为wi的有向边。

2 <= n <= 300

0 <= m <= n(n <= 1)

1 <= ui, vi <= n

|wi| <= 10^4

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


先开$Logn$个矩阵$dis$,$dis[i][j][k]$表示从$j$到$k$走$2^{i}$条边的最短路。

然后像倍增$lca$那样,再从大到小找到最后一个没有负环的矩阵,再乘一次初始矩阵,判断有没有负环即可。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 350
int f[N][N][20],n,m,L[N];
struct Mat {
    int v[301][301];
    Mat(){memset(v,0x3f,sizeof(v));}
    Mat operator*(const Mat &x)const {
        Mat re;int i,j,k;
        for(k=1;k<=n;k++) {
            for(i=1;i<=n;i++) {
                for(j=1;j<=n;j++) {
                    re.v[i][j]=min(re.v[i][j],v[i][k]+x.v[k][j]);
                }
            }
        }
        return re;
    }
}dis[10];
bool judge(Mat x) {
    int i;
    for(i=1;i<=n;i++) {
        if(x.v[i][i]<0) return 1;
    }
    return 0;
}
int main() {
    scanf("%d%d",&n,&m);
    int i,x,y,z,sum=0;
    Mat tmp;
    for(i=1;i<=n;i++) dis[0].v[i][i]=tmp.v[i][i]=0;
    for(i=2;i<=n;i++) L[i]=L[i>>1]+1;
    for(i=1;i<=m;i++) {
        scanf("%d%d%d",&x,&y,&z);
        dis[0].v[x][y]=z;
    }
    for(i=1;i<=L[n];i++) dis[i]=dis[i-1]*dis[i-1];
    for(i=L[n];i>=0;i--) {
        if(!judge(tmp*dis[i])) {
            tmp=tmp*dis[i]; sum+=(1<<i);
        }
    }
    tmp=tmp*dis[0];
    printf("%d\n",judge(tmp)?sum+1:0);
}

原文地址:https://www.cnblogs.com/suika/p/8893205.html

时间: 2024-11-13 08:06:43

BZOJ_4773_负环_倍增弗洛伊德的相关文章

【BZOJ4773】负环 倍增Floyd

[BZOJ4773]负环 Description 在忘记考虑负环之后,黎瑟的算法又出错了.对于边带权的有向图 G = (V, E),请找出一个点数最小的环,使得 环上的边权和为负数.保证图中不包含重边和自环. Input 第1两个整数n, m,表示图的点数和边数. 接下来的m行,每<=三个整数ui, vi, wi,表<=有一条从ui到vi,权值为wi的有向边. 2 <= n <= 300 0 <= m <= n(n <= 1) 1 <= ui, vi <

bzoj4773 负环 倍增+矩阵

题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4773 题解 最小的负环的长度,等价于最小的 \(len\) 使得存在一条从点 \(i\) 到自己存在一条长度 \(\leq len\) 的负权路径. 为了把 \(\leq len\) 转化为 \(=len\),我们可以给每一个点建立有个边权为 \(0\) 的自环. 所以考虑倍增邻接矩阵,维护两点之间的经过 \(2^i\) 条边的最短路. 倍增的时候判断走了那么多步有没有负环就可以了. 最后结

BZOJ4773: 负环

倍增floyd裸题,倍增判断走2^i步是否存在负环就好了. 其实和3763是一样的,然而那题数据挂了. #include<cstdio> void upd1(int&a,int b){ if(a>b)a=b; } const int N=301; typedef int arr[N][N]; int n; void pre(arr a){ for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) a[i][j]=1e9; } void d

负环 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

一种科学的判断负环的方法

判断负环的方法 ------------ 这里有个叫分界线的家伙突然想说,本章主体思路都是在 SPFA 上的o ------------ 感觉分为两种大方向,\(BFS\) 和 \(DFS\) 快速写一下 \(BFS\) 的思路 由 \(SPFA\) 的算法可以发现,如果要更新一个点的 \(dis\) ,那么一定有一个点先被更新了以后,然后通过这个新更新的点来更新这个点,那么在没有负环的情况下,一个点能被更新的最多次数为 \(n\) 次,也就是说,如果一个点进队的次数大于 \(n\) 了,嘿嘿嘿

poj 3259 Wormholes(bellman-ford判断负环)

题目链接:http://poj.org/problem?id=3259 题目就是问你能否回到原点而且时间还倒回去了.题目中有些路中有单向的虫洞能让时间回到过去 所以只要将虫洞这条边的权值赋为负然后再判断有没有负环就行了. #include <iostream> #include <cstring> using namespace std; const int inf = 10001; int f , n , m , w ,dis[1001] , counts; struct TnT

(简单) LightOJ 1074 Extended Traffic,SPFA+负环。

Description Dhaka city is getting crowded and noisy day by day. Certain roads always remain blocked in congestion. In order to convince people avoid shortest routes, and hence the crowded roads, to reach destination, the city authority has made a new

POJ 3259 虫洞旅行 spfa判负环

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 31425   Accepted: 11431 Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way p

洛谷P3385 【模板】负环 DFS-SPFA 判负环 图论

洛谷P3385 [模板]负环 图论 今天get了 一个 DFS-SPFA 判负环的方法 一般的 BFS-SPFA 判负环 一般就是 不停地做,如果某点第 n+1次加入队列中,那么说明这个图存在负环然而我并不会证明,期望复杂度是 O(kM) k 大约是在 2 左右 但是其实对于一些极限数据,最坏可以把他卡到 O( NM) 额,这就直接炸飞了是不是,而且据说,一些数据比较强的题目,总会想到卡一卡SPFA的, 然后我们换一种思路 因为题目中一定存在一种 负环对吧,所以说假如你某段路径权值和为自然数的时