首页 > 其他分享 >找负环(图论基础)

找负环(图论基础)

时间:2024-02-15 19:55:26浏览次数:26  
标签:pb 图论 int rep 基础 long 负环 define

目录

负环

1707991801509.png
环内路径上的权值和为负。

spfa找负环

两种基本的方法

  1. 统计每一个点的入队次数,如果一个点入队了n次,则说明存在负环
  2. 统计当前每个点中的最短路中所包含的边数,如果当前某个点的最短路所包含的边数大于等于n,也说明存在负环

实际上两种方法是等价的,都是判断是否路径包含n条边,\(n\)条边的话就有\(n+1\)个点
用的更多的还是第二种方法。

方法一

\(cnt[x]:表示x的入队次数\)

#include <bits/stdc++.h> 
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define pii pair<int, int>
#define ll long long
#define db double
#define endl '\n'
#define x first
#define y second
#define pb push_back
#define inf 0x3f3f3f3f*1ll

using namespace std;

void solve()
{
	int n,m1,m2;
	cin>>n>>m1>>m2;
	vector<vector<pii>>g(n+1);
	rep(i,1,m1){
		int u,v,w;
		cin>>u>>v>>w;
		g[u].pb({v,w});
		g[v].pb({u,w});
	}	
	rep(i,1,m2){
		int u,v,w;
		cin>>u>>v>>w;
		g[u].pb({v,-w});
	}
	vector<int>inq(n+1,0);
	vector<int>cnt(n+1,0);
	vector<int>d(n+1,0);
	queue<int>q;
	rep(i,1,n){
		q.push(i);
		inq[i]=1;
	}
	while(q.size()){
		auto t=q.front();
		q.pop();
		int u=t;
		inq[u]=0;
		for(auto it:g[u]){
			int v=it.x,w=it.y;
			if(d[v]>d[u]+w){
				d[v]=d[u]+w;
				if(!inq[v]){
					q.push(v);
					inq[v]=1;
					cnt[v]++;
					if(cnt[v]>=n){
					cout<<"YES"<<endl;
					return;
					}
				}
			}
		}
	}
	cout<<"NO"<<endl;
}

signed main(){
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//   	freopen("1.in", "r", stdin);
	int _;
	cin>>_;
	while(_--)
	solve();
	return 0;
}

方法二

\(cnt[x]:表示从起点到x所经过的最短路径的边数\)

#include <bits/stdc++.h> 
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define pii pair<int, int>
#define ll long long
#define db double
#define endl '\n'
#define x first
#define y second
#define pb push_back
#define inf 0x3f3f3f3f*1ll

using namespace std;

void solve()
{
	int n,m1,m2;
	cin>>n>>m1>>m2;
	vector<vector<pii>>g(n+1);
	rep(i,1,m1){
		int u,v,w;
		cin>>u>>v>>w;
		g[u].pb({v,w});
		g[v].pb({u,w});
	}	
	rep(i,1,m2){
		int u,v,w;
		cin>>u>>v>>w;
		g[u].pb({v,-w});
	}
	vector<int>inq(n+1,0);
	vector<int>cnt(n+1,0);
	vector<int>d(n+1,0);
	queue<int>q;
	rep(i,1,n){
		q.push(i);
		inq[i]=1;
	}
	while(q.size()){
		auto t=q.front();
		q.pop();
		int u=t;
		inq[u]=0;
		for(auto it:g[u]){
			int v=it.x,w=it.y;
			if(d[v]>d[u]+w){
				d[v]=d[u]+w;
				cnt[v]=cnt[u]+1;
				if(cnt[v]>=n){
					cout<<"YES"<<endl;
					return;
				}
				if(!inq[v]){
					q.push(v);
					inq[v]=1;
				}
			}
		}
	}
	cout<<"NO"<<endl;
}

signed main(){
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//   	freopen("1.in", "r", stdin);
	int _;
	cin>>_;
	while(_--)
	solve();
	return 0;
}

实际效果

1707997993525.png
1707997579479.png
方法一跑出来的结果是\(1024ms\)
方法二跑出来的结果是\(671ms\)

标签:pb,图论,int,rep,基础,long,负环,define
From: https://www.cnblogs.com/cxy8/p/18016459

相关文章

  • [Kyana]逆向安卓基础
    APK文件结构assets:不需要编译的资源文件lib:.so动态链接库文件,C/C++编译后文件META-INF:所有文件的摘要信息res:编译过的资源文件(图标、布局等)AndroidManifest:安卓设备配置文件classes.dex:Java代码编译后文件resources.arsc:字符串样式等资源APK打包流程AADT编译资源文件,......
  • 动态规划基础笔记
    背包问题 01背包  一般的动态规划要先考虑好状态,这个状态是一个集合,要能分成几个子集,然后从这些子集(小问题),推到这一整个集合(大问题),且求解过程是一样的,就可以可以转换成大问题分解成小问题一个一个求解,最后合并先要知道状态表示什么再要知道dp的属性,应该跟所求有关,只会......
  • 数论基础
    数论:研究数与数之间的关系。如带余除法、因数倍数、同余整除等都是数论。【筛法】主要使用的筛法有两个:埃氏筛和欧拉筛(线性筛)。使用筛法的原因很简单:对于一个数,我们要找它的因数不容易;但是对于一个因数,我们找它的倍数很简单。【埃氏筛】因为一个数的倍数一定不是质数,且任何数......
  • 线性代数基础
    元素:一个个体,一般是一个数。【向量】向量:一组元素,向量\(a\)记作\(\vec{a}\)。我们只在乎向量的方向和大小,并不在乎向量的起点和终点。定义:\(n\)维向量,即\(\vec{a}\)中包含\(n\)个元素。向量的运算:向量的大小:\(|\vec{a}|\)。向量加减:只有两个规模相等的向量的......
  • 组合基础
    OI中的组合,基本指组合计数。组合极值一般是贪心题或者dp题。【组合数】组合数\(C^m_n=(^n_m)\)。注意:求逆元前,请一定判断清楚,是否可能不存在逆元!!!\(C^m_n=C^m_{n-1}+C^{m-1}_{n-1}\)。c[n][m]=c[n-1][m]+c[n-1][m-1];这个方法主要问题在于空间。优点:可以......
  • 基础图论笔记
    二分图  染色法  例题ACwing860-染色法判断二分图(染色法)-CSDN博客给定一个n个点m条边的无向图,图中可能存在重边和自环。请你判断这个图是否是二分图。输入格式第一行包含两个整数n和m。接下来m行,每行包含两个整数u和v,表示点u和点v之间存在一条边。输出格式如......
  • 图论题目合集
    题面:要求把\(1\simn\)排序,满足给定的所有条件,满足条件之后,编号越小要越靠前。(满足条件情况下,先让1最靠左,然后让2……)每个条件会给出两个数\(a,b\),表示\(a\)必须在\(b\)之前。解答:看起来很像拓扑排序。于是我们对于每个条件\(a,b\),从\(a\)向\(b\)连一条边。每......
  • Lag-Llama:第一个时间序列预测的开源基础模型介绍和性能测试
    2023年10月,我们发表了一篇关于TimeGPT的文章,TimeGPT是时间序列预测的第一个基础模型之一,具有零样本推理、异常检测和共形预测能力。虽然TimeGPT是一个专有模型,只能通过API访问。但是它还是引发了对时间序列基础模型的更多研究。到了2024年2月,已经有了一个用于时间序列预测的开源......
  • 《从基础认识相对论的错误》 回复
    《从基础认识相对论的错误》      https://tieba.baidu.com/p/8895510201     这帖是你昨天发的, 10天前,你发了  《相对论对物理理论的影响是什么?》   https://tieba.baidu.com/p/8885351309  , 半年前,  我发过《@东方已晓的反相观点》......
  • python基础学习6-第三方模块
    自定义模块优先级大于系统模块模块分为系统模块,自定义模块,第三方模块导入方式import模块名称[as别名]from模块名称import变量/函数/类*包的导入import包名.模块名as别名form包名import模块名as别名form包名.模块名import函数/变量/类*主程序运行i......