负环与差分约束

 之前觉得自己写的负环不是很好,今天想再写一遍。

负环

 负环,又叫负权回路,负权环,指的是一个图中存在一个环,里面包含的边的边权总和 < 0 \lt0 <0。在存在负环的图中,是求不出最短路径的,因为只要在这个环上不停的兜圈子,最短路径就会无限小。

 定理:如果一个点的入队的次数大于点的总数 N N N,则存在负权回路。
 若图中没有负环,则最多经过 n − 1 n-1 n1轮迭代后算法结束。所以若第 n n n轮迭代仍有结点的最短路能被更新,则图中有负环。
 所以我们用 c n t [ x ] cnt[x] cnt[x]表示 1 1 1 x x x的最短路包含的边数(该题要求以 1 1 1作为源点), c n t [ 1 ] = 0 cnt[1]=0 cnt[1]=0。每次用 d i s [ x ] + w ( x , y ) dis[x]+w(x,y) dis[x]+w(x,y)更新 d i s [ y ] dis[y] dis[y]时,也是 c n t [ x ] + 1 cnt[x]+1 cnt[x]+1更新 c n t [ y ] cnt[y] cnt[y]。此过程中若出现 c n t [ y ] ≥ n cnt[y]≥n cnt[y]n,则图中有负环。最坏情况复杂度也是 O ( n m ) O(nm) O(nm)

 参考代码

#include<bits/stdc++.h>
#define in read()
#define MAXN 3003
#define MAXM 2*MAXN
using namespace std;
int T,n,m;
int nex[MAXM],first[MAXM],to[MAXM],val[MAXM],tot=0;
bool vis[MAXN];
int cnt[MAXN],dis[MAXN]; 
queue<int>q;

inline int read(){
   
	int x=0,f=1;char c=getchar();
	while(c<'0' or c>'9'){
   if(c=='-')f=-1;c=getchar();}
	while(c>='0' and c<='9'){
   x=(x<<3)+(x<<1)+c-'0';c=getchar();}
	return x*f;
}

inline void addedge(int u,int v,int w){
   //建图
	nex[++tot]=first[u];
	first[u]=tot;
	to[tot]=v;
	val[tot]=w;
}

inline void prework(){
   //初始化
	memset(first,0,sizeof(first));
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值