【洛谷 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 ...
随机推荐
- aspcms常见问题解决方案
1.产品详细页读取多张产品图片(栏目类型:产品){aspcms:cimages count=16 contentid=[content:id]}<li onmouseover="sho ...
- 比较下OceanBase的选举协议和Raft的选举协议的区别
阿里技术大讲堂OceanBase专场中曾有专门一场讲座介绍OB自己实现的分布式选举算法:<分布式选举-破解数据库高可用性难题> 这里简单列一下这个选举算法和raft论文中提到的选举算法的区 ...
- 日本超人气洛比(Robi)声控机器人
1.日本超人气洛比(Robi)声控机器人. http://technews.cn/2015/04/18/interview-with-robi-creator-tomotaka-takahashi/ ...
- 拼音 名字 排序 a-z的比较 ( sortUsingComparator )
NSMutableArray * array = [NSMutableArrayarrayWithObjects:@"ad",@"az",@"ac&q ...
- CyanogenMod wiki reading tips | Android tips
To Enable the Developer and Performance settings on CyanogenMod 10.1 In the Settings app, choose the ...
- PE渲染引擎 三
加进了SSAO,讲真这个东西,很容易忽略他的存在.并且动态的话,会有闪烁. 下面两幅图,单独给你看一张,应该看不出去区别....依旧是浓重风格,这个tongmaping,哪位大神指教下.....
- DDD:群里关于验证的结论
@汤雪华 验证是为了让数据符合要求.各个层的验证是为了确保传递给各个层的数据符合当前层所需要的数据的要求. @小学僧 db model的验证主要是为了保证数据完整. domain model的验证主要 ...
- yousa_team团队项目 兼职平台 完成展示
我们团队的团队项目是一个大学生兼职网站,商家可以在网站上发布信息,学生对相应的岗位进行预约,然后根据信誉度来表示用户的信誉,整个平台由管理员监控, 包括修改错误信息,修改用户信誉度,删除过期信息,接受 ...
- [Solution] 1分钟使用log4net
log4net库是Apache log4j框架在Microsoft .NET平台的实现,是一个帮助程序员将日志信息输出到各种目标(控制台.文件.数据库等)的工具 官网:http://logging.a ...
- SeaJS 模块化加载框架使用
SeaJS 是一个遵循 CMD 规范的模块化加载框架 CommonJS,CMD,AMD等规范后文会提到,这里主要先了解如何在代码中使用. 如果你有使用过nodejs ,那么理解起来就容易多了. 我们通 ...