[P3385]【模板】负环 (spfa / bellman-ford)
终于开始认真对待图论了
因为听说一直是提高组的,动得很少,直到现在机房打提高的氛围下,开始学一些皮毛的东西
这是一道求负环的题目,照理来说大家都是用spfa来判断负环的
但是我觉得bellman-ford更优
并且在这个模板题目中,spfa开O2过,bellman不开O2还比spfa快?
为什么呢?
因为
关于spfa
——他死了
(所以机房基本所有人转dijistra了)
但是dijistra无法解决负环问题
因此选择bellman和spfa(队列优化的bellman)
其实还可以用其他方法过掉,比如
SPFA他死了算法
思路
因为出现负环的时候会一直循环循环循环……
然后TLE
所以在原版spfa上加一个cnt数组记录一个点出队的次数
如果出队次数大于点数,就说明一定出现负环了
因此加给判断就可以了
题外话
之前xzjds给我讲了邻接表储存,但是后来发现其实广泛叫做链式前向星而不是叫做邻接表……
如果不会的话可以百度
要储存边的话还可以用向量容器和玄学结构体(将会在bellman里使用)
代码
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define memset0(a) memset(a,0,sizeof a)
#define memset1(a) memset(a,127,sizeof a)
#define N 500005
using namespace std;
int tot,m,n,s;
int ne[N], la[N], link[N], co[N], dis[N];
int cnt[N];//important
bool vis[N];
inline int read() {
int f = , x = ; char ch;
do { ch = getchar(); if (ch == '-')f = -; } while (ch<'' || ch>'');
do { x = x * + ch - ''; ch = getchar(); } while (ch >= ''&&ch <= '');
return f * x;
}
void add(int x, int y, int z)
{
tot++; ne[tot] = y; co[tot] = z; la[tot] = link[x]; link[x] = tot;
}
bool spfa(int s)
{
memset1(dis);
memset0(vis);
memset0(cnt); queue<int>q;
q.push(s);
vis[s] = true;
dis[s] = ;
while (!q.empty())
{
int now = q.front();
q.pop();
vis[now] = false;//?
if (cnt[now] >= n) return true;
for (int k = link[now]; k; k = la[k])
{
if (dis[ne[k]] > dis[now] + co[k])
{
dis[ne[k]] = dis[now] + co[k];
if (vis[ne[k]] == false)
{
q.push(ne[k]);
vis[ne[k]] = true;
cnt[ne[k]]++;
if (cnt[ne[k]] >= n) return true;
}
}
}
}
return false;
}
int main()
{
int T=read();
while (T--)
{
memset0(link);
n = read(), m = read();
s = ; tot = ;
; for (int i = ; i <= m; i++)
{
int x=read(), y=read(), z=read();
add(x, y, z);
if (z >= ) add(y, x, z);
}
if(spfa(s))puts("YE5");
else puts("N0");
}
return ;
}
spfa
是的,不加O2会TLE。只有90分。
由于本蒟蒻不会优化,因此学习了更好的bellman判断负环
Bellman-ford算法
思路
可以把dis数组一开始都设为0
先全部松弛操作一遍(relaxing一遍)
然后再去松弛,如果能松弛,就是有负环
这个相对spfa来说,当数据点数小的时候,时间是比spfa快的
当然如果RP不好spfa速度会更快
为什么每次都有题外话
用的边的储存方式是从大佬@Planet6174 看来的
感觉非常玄学但是很容易使用
代码
#include<bits/stdc++.h>
#define N 500005
using namespace std;
int tot,m,n,s;
int dis[N];
inline int read() {
int f = , x = ; char ch;
do { ch = getchar(); if (ch == '-')f = -; } while (ch<'' || ch>'');
do { x = x * + ch - ''; ch = getchar(); } while (ch >= ''&&ch <= '');
return f * x;
}
struct eg{
int u,v,w;
eg(int u = , int v = , int w = ) : u(u), v(v), w(w) {}
} edge[N];
bool bellman_ford()
{
memset(dis,,sizeof(dis));
for(int i=;i<=n-;i++)
for(int j=;j<=m;j++)
if (dis[edge[j].u] + edge[j].w < dis[edge[j].v])
dis[edge[j].v] = dis[edge[j].u] + edge[j].w;
for (int j = ; j <= m; j++)
if (dis[edge[j].u] + edge[j].w < dis[edge[j].v])
return true;
return false; }
int main()
{
int T=read();
while (T--)
{
n = read(), m = read();
; for (int i = ; i <= m; i++)
{
edge[i].u=read(), edge[i].v=read(), edge[i].w=read();
edge[i].u--; edge[i].v--;
if (edge[i].w >= ) {
++i; ++m; edge[i] = eg(edge[i - ].v, edge[i - ].u, edge[i - ].w);
}
}
if(bellman_ford()) puts("YE5");
else puts("N0");
}
return ;
}
bellman-ford
就是这样了
[P3385]【模板】负环 (spfa / bellman-ford)的更多相关文章
- 洛谷P3385 [模板]负环 [SPFA]
		
题目传送门 题目描述 暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索 输入输出格式 输入格式: 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M,表示图有N个 ...
 - 洛谷P3385判负环——spfa
		
题目:https://www.luogu.org/problemnew/show/P3385 两种方法,dfs和bfs: 一开始写的dfs,要把dis数组初值赋成0,这样从一个连着负边的点开始搜: 在 ...
 - LG P2285 [模板]负环(spfa判负环)
		
题目描述 寻找一个从顶点1所能到达的负环,负环定义为:一个边权之和为负的环. 输入格式 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M,表示图有N个顶点,M条边 接下来M行,每 ...
 - 【洛谷 P3385】模板-负环(图论--spfa)
		
题目:有一个图有N个顶点,M条边.边用三个整数a b w表示,意思为a->b有一条权值为w的边(若w<0则为单向,否则双向).共T组数据.对于每组数据,存在负环则输出一行"YE5 ...
 - Spfa【p3385】【模板】负环(spfa)
		
顾z 你没有发现两个字里的blog都不一样嘛 qwq 题目描述 毒瘤数据要求判负环 分析: 还是融合了不少题解的思想的. 负环定义: 权值和为负的环 //在网络上并没有找到一个官方定义,暂且这么理解. ...
 - 洛谷 P3385 【模板】负环  (SPFA)
		
题意:有一个\(n\)个点的有向图,从\(1\)出发,问是否有负环. 题解:我们可以用SPFA来进行判断,在更新边的时候,同时更新路径的边数,因为假如有负环的话,SPFA这个过程一定会无限重复的遍历这 ...
 - 【洛谷P3385】模板-负环
		
这道题普通的bfs spfa或者ballen ford会T 所以我们使用dfs spfa 原因在于,bfs sfpa中每个节点的入队次数不定,退出操作不及时,而dfs则不会 既然,我们需要找负环,那么 ...
 - 负环--spfa
		
洛谷板子题 负环?是有负权边的环还是一个边权之和为负的环? 还没有准确的定义(那就先忽略吧qwq 判断负环的方法: 暴力枚举/spfa/mellman—ford/奇怪的贪心/超神的搜索 可惜我只会sp ...
 - luogu3385 负环 (spfa)
		
我在做spfa的时候,如果有一个点被更新了超过N次,证明这个图里是有负环的. (神TM输出YE5和N0) #include<bits/stdc++.h> #define pa pair&l ...
 
随机推荐
- Eclipes导入工程
			
1.在eclipes中导入其他的一些工程后往往会出错,修改意见是 在project.properties该文件下修改 这个target是你的sdk中已经下载好的 查看: 右键目标工程,选择proper ...
 - VS和IIS的一些问题
			
运行所有MVC一直502,重启了iis服务, 之后弹出这个框: 之后的解决办法: 1. If you open the applicationhost,config file in VS while ...
 - python多线程爬取-今日头条的街拍数据(附源码加思路注释)
			
这里用的是json+re+requests+beautifulsoup+多线程 1 import json import re from multiprocessing.pool import Poo ...
 - Redis托管Session
			
一:redis托管session主要是为了不同域之间共享session.Asp.net提供了四种处理Session的方法 1. InProc模式 这是ASP.NET默认的Session管理模式,在应 ...
 - Vuex详解笔记1
			
vuex 是什么Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 什么是状态?状态这里泛指 ...
 - Java 集合Collection与List的详解
			
1.什么是集合 存储对象的容器,面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,存储对象,集合是存储对象最常用的一种方式. 集合的出现就是为了持有对象.集合中可以存储任意类型的 ...
 - bzoj3769 spoj 8549 BST again
			
题解: 比较水的题目 普通dp其实复杂度还是比较大的 可以任意模数ntt优化.. 但好像没人写.. 代码: #include <bits/stdc++.h> using namespace ...
 - 在vs.net 2010,2015 等版本,给JS函数添加代码提示\注释
			
经常编写JS的朋友常常会因为函数写多了,隔一段时间就会忘记了函数的用途,或者函数里带的参数作用情况,这个时候会联想到VS工具里的强大提示功能,多希望也能在JS上实现呀,告诉你,这个想法并不是多难,VS ...
 - Codeforces 1076F Summer Practice Report dp
			
Summer Practice Report dp[ i ][ 0 ]表示放完前 i 页, 第 i 页最后一段是 0, 0个数的最小值. dp[ i ][ 1 ]表示放完前 i 页, 第 i 页最后一 ...
 - 借助CSS Shapes实现元素滚动自动环绕iPhone X的刘海
			
CSS代码: .box { max-width: 414px; height: 480px; border: solid #000; margin: auto; overflow: auto; } . ...