【洛谷 P3385】模板-负环(图论--spfa)
题目:有一个图有N个顶点,M条边。边用三个整数a b w表示,意思为a->b有一条权值为w的边(若w<0则为单向,否则双向)。共T组数据。对于每组数据,存在负环则输出一行"YE5"(不含引号),否则输出一行"N0"(不含引号)。
注意——坑爹的输出啊!!它不是平常的 YES 和 NO!!
解法:1.spfa_bfs,判断结点入队超过 n 次就出现负环。最差的情况是O(nm)。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std; const int N=;
struct edge{int x,y,d,next;}a[N*];
int last[N],vis[N],cnt[N],d[N];
int len,n,m;
queue<int> q; void ins(int x,int y,int d)
{
a[++len].x=x,a[len].y=y,a[len].d=d;
a[len].next=last[x],last[x]=len;
}
bool spfa()
{
while (!q.empty()) q.pop();
memset(d,,sizeof(d));
memset(cnt,,sizeof(cnt));
memset(vis,,sizeof(vis));
d[]=,vis[]=,cnt[]++;
q.push();
while (!q.empty())
{
int x=q.front();
q.pop(); vis[x]=;//此处无cnt++
for (int i=last[x];i!=-;i=a[i].next)
{
int y=a[i].y;
if (d[x]+a[i].d<d[y])
{
d[y]=d[x]+a[i].d;
if (!vis[y])
{
q.push(y);
vis[y]=, cnt[y]++;
if (cnt[y]>n) return true;
}
}
}
}
return false;
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&n,&m);
int x,y,d; len=;
memset(last,-,sizeof(last));
for (int i=;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&d);
ins(x,y,d);
if (d>=) ins(y,x,d);
}
if (spfa()) printf("YE5\n");
else printf("N0\n");
}
return ;
}
bfs TLE
2.spfa_dfs,枚举起点,找最短路,若再一次访问到已经访问过的结点就出现负环。最差的情况也是O(nm)。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std; const int N=,INF=(int)1e9;
struct edge{int x,y,d,next;}a[N*];
int last[N],vis[N],dis[N];
int len,n,m; void ins(int x,int y,int d)
{
a[++len].x=x,a[len].y=y,a[len].d=d;
a[len].next=last[x],last[x]=len;
}
bool dfs(int x)
{
if (vis[x]) return true;
vis[x]=;
for (int i=last[x];i!=-;i=a[i].next)
{
int y=a[i].y;
//if (y==fa) continue;//有dis的判断
if (dis[x]+a[i].d<dis[y])
{
dis[y]=dis[x]+a[i].d;
if (dfs(y)) return true;
}
}
vis[x]=;//判断一个点是否在“同一”路径重复出现而已。
return false;//
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&n,&m);
int x,y,d; len=;
memset(last,-,sizeof(last));
for (int i=;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&d);
ins(x,y,d);
if (d>=) ins(y,x,d);
}
for (int i=;i<=n;i++) dis[i]=INF;
memset(vis,,sizeof(vis));
dis[]=;//起点不确定的!
if (dfs()) printf("YE5\n");
else printf("N0\n");
}
return ;
}
dfs WA(起点不能只是随便定一个点)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long LL; const int N=,D=;
const LL INF=(LL)5e10;
int n,m,len;
bool cir;
int last[N],vis[N];
LL dis[N];
struct edge{int x,y,next;LL d;}a[*N]; void ins(int x,int y,LL d)
{
a[++len].x=x,a[len].y=y,a[len].d=d;
a[len].next=last[x],last[x]=len;
}
void dfs(int x)
{
if (vis[x]) {cir=true;return;}
vis[x]=;
for (int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if (dis[x]+a[i].d<dis[y])
{
dis[y]=dis[x]+a[i].d;
dfs(y);
if (cir) return;
}
}
vis[x]=;
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
int x,y; LL d;
len=;
memset(last,,sizeof(last));
scanf("%d%d",&n,&m);
for (int i=;i<=m;i++)
{
scanf("%d%d%lld",&x,&y,&d);
ins(x,y,d);
if (d>=) ins(y,x,d);
}
cir=false;
for (int i=;i<=n;i++)
{
for (int j=;j<=n;j++) dis[j]=INF;
memset(vis,,sizeof(vis));
dis[i]=, dfs(i);
if (cir) break;
}
if (cir) printf("YE5\n");
else printf("N0\n");
}
return ;
}
dfs TLE
3.spfa_dfs+优化,既然是找负环,那么就是找权和为负数的回路。P.S.这个一定要理解!!ヾ(。 ̄□ ̄)ツ゜゜゜我想了很久......网上也没搜到。负环负环,不单单是含负权边的环,而是权和为负的环。原因是对于一个在负环里的点,只有经过负环后的距离还比原来的小,才会再一次访问该点。要不怎么会一直循环走这个环,直到RE呢......ヘ(_ _ヘ) 也就是环的权和为负数!
实现就是我们对 dis 数组清零,再权和为负的情况下做spfa,且使用 dfs 判断成环。时间复杂度远远小于O(nm)。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long LL; const int N=,D=;
const LL INF=(LL)5e10;
int n,m,len;
bool cir;
int last[N],vis[N];
LL dis[N];
struct edge{int x,y,next;LL d;}a[*N]; void ins(int x,int y,LL d)
{
a[++len].x=x,a[len].y=y,a[len].d=d;
a[len].next=last[x],last[x]=len;
}
void dfs(int x)
{
if (vis[x]) {cir=true;return;}
vis[x]=;
for (int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if (dis[x]+a[i].d<dis[y])
{
dis[y]=dis[x]+a[i].d;
dfs(y);
if (cir) return;
}
}
vis[x]=;
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
int x,y; LL d;
len=;
memset(last,,sizeof(last));
scanf("%d%d",&n,&m);
for (int i=;i<=m;i++)
{
scanf("%d%d%lld",&x,&y,&d);
ins(x,y,d);
if (d>=) ins(y,x,d);
}
memset(dis,,sizeof(dis));
memset(vis,,sizeof(vis));
cir=false;
for (int i=;i<=n;i++)
{
dfs(i);
if (cir) break;
}
if (cir) printf("YE5\n");
else printf("N0\n");
}
return ;
}
dfs AC
【洛谷 P3385】模板-负环(图论--spfa)的更多相关文章
- 洛谷P3385 [模板]负环 [SPFA]
题目传送门 题目描述 暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索 输入输出格式 输入格式: 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M,表示图有N个 ...
- 洛谷P3385判负环——spfa
题目:https://www.luogu.org/problemnew/show/P3385 两种方法,dfs和bfs: 一开始写的dfs,要把dis数组初值赋成0,这样从一个连着负边的点开始搜: 在 ...
- 洛谷 P3385 【模板】负环 (SPFA)
题意:有一个\(n\)个点的有向图,从\(1\)出发,问是否有负环. 题解:我们可以用SPFA来进行判断,在更新边的时候,同时更新路径的边数,因为假如有负环的话,SPFA这个过程一定会无限重复的遍历这 ...
- 洛谷—— P3385 【模板】负环
题目描述 暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索 输入输出格式 输入格式: 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M,表示图有N个顶点,M条边 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- poj3259,简单判断有无负环,spfa
英语能力差!百度的题意才读懂!就是一个判断有无负环的题.SPFA即可.,注意重边情况!! #include<iostream> //判断有无负环,spfa #include<queu ...
- 【模板】负环(SPFA/Bellman-Ford)/洛谷P3385
题目链接 https://www.luogu.com.cn/problem/P3385 题目大意 给定一个 \(n\) 个点有向点权图,求是否存在从 \(1\) 点出发能到达的负环. 题目解析 \(S ...
- 洛谷P3385 【模板】负环(DFS求环)
洛谷题目传送门 HNOI爆零前回刷模板题 非常不正经的题目,目前并没有合适的优秀算法,就算是大家公认的dfs(还是不要强行叫dfs-spfa吧,概念应该不一样,这就是暴力dfs松弛答案) 但是对于随机 ...
- 洛谷 P3385 【模板】负环
P3385 [模板]负环 题目描述 暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索 输入输出格式 输入格式: 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M ...
随机推荐
- 给The Lab Renderer for Unity中地形添加阴影
The Lab Renderer for Unity是Valve针对VR在Unity的体验渲染器,提高VR的渲染效率,更多的大家可以查相应资料,在这,说个The Lab Renderer for Un ...
- (笔记)Linux内核学习(十一)之I/O层和I/O调度机制
一 块I/O基本概念 字符设备:按照字符流的方式被有序访问的设备.如串口.键盘等. 块设备:系统中不能随机(不需要按顺序)访问固定大小的数据片(chunk 块)的设备. 如:硬盘.软盘.CD-ROM驱 ...
- 一个JAVA数据库连接池实现源码
原文链接:http://www.open-open.com/lib/view/open1410875608164.html // // 一个效果非常不错的JAVA数据库连接池. // from:htt ...
- 【Android】与服务器实现JSON数据通信
一.前言 作为一名移动端开发人员,具备一定的服务端开发能力也是非常必要的,本篇博客讲述如何在Android和服务器之间实现JSON数据通信交互,博客内容基于另外一篇博客:[Web]Eclipse + ...
- [转]make: 警告:检测到时钟错误。您的创建可能是不完整的。
转自http://blog.csdn.net/maopig/article/details/6599660 我在make的时候也出现了同样的问题,不过不是什么大问题,这个不影响编译结果 分析原因可能是 ...
- imagepng或imagejpeg浏览器无显示问题
可以先参考这篇文章,检查一下php的文件编码是否有bom 然而我并不是这个问题,后来想到或许是输出缓冲中有其它内容, 于是尝试 ob_clean();$imagepng($im);或//imagejp ...
- Reinforcement Learning
Q-learning 高潮博文 http://mnemstudio.org/path-finding-q-learning-tutorial.htm 模式识别与机器学习的区别. http://www. ...
- iOS-沙盒路径总结、文件管理NSFileManager总结
// // ViewController.m // 沙盒操作 // // Created by mncong on 15/11/26. // Copyright © 2015年 mancong ...
- Entity Framework的默认值BUG解决方法
在使用.Net 3.5里的Entity Framework开发网站的时候,遇到了一个问题:添加记录时,对于DateTime型的数据,无法使用数据库的默认值. 具体的情况是这样的,我的数据库有个User ...
- mysql 输出当前月所有日期与对应的星期
其实可以用存储过程,但想用另一种方法实现: 首先创建一个辅助表,可以设置CREATE TABLE `t4` ( `id` ) NOT NULL AUTO_INCREMENT, `num` ) DEFA ...