题目:有一个图有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)的更多相关文章

  1. 洛谷P3385 [模板]负环 [SPFA]

    题目传送门 题目描述 暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索 输入输出格式 输入格式: 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M,表示图有N个 ...

  2. 洛谷P3385判负环——spfa

    题目:https://www.luogu.org/problemnew/show/P3385 两种方法,dfs和bfs: 一开始写的dfs,要把dis数组初值赋成0,这样从一个连着负边的点开始搜: 在 ...

  3. 洛谷 P3385 【模板】负环 (SPFA)

    题意:有一个\(n\)个点的有向图,从\(1\)出发,问是否有负环. 题解:我们可以用SPFA来进行判断,在更新边的时候,同时更新路径的边数,因为假如有负环的话,SPFA这个过程一定会无限重复的遍历这 ...

  4. 洛谷—— P3385 【模板】负环

    题目描述 暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索 输入输出格式 输入格式: 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M,表示图有N个顶点,M条边 ...

  5. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  6. poj3259,简单判断有无负环,spfa

    英语能力差!百度的题意才读懂!就是一个判断有无负环的题.SPFA即可.,注意重边情况!! #include<iostream> //判断有无负环,spfa #include<queu ...

  7. 【模板】负环(SPFA/Bellman-Ford)/洛谷P3385

    题目链接 https://www.luogu.com.cn/problem/P3385 题目大意 给定一个 \(n\) 个点有向点权图,求是否存在从 \(1\) 点出发能到达的负环. 题目解析 \(S ...

  8. 洛谷P3385 【模板】负环(DFS求环)

    洛谷题目传送门 HNOI爆零前回刷模板题 非常不正经的题目,目前并没有合适的优秀算法,就算是大家公认的dfs(还是不要强行叫dfs-spfa吧,概念应该不一样,这就是暴力dfs松弛答案) 但是对于随机 ...

  9. 洛谷 P3385 【模板】负环

    P3385 [模板]负环 题目描述 暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索 输入输出格式 输入格式: 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M ...

随机推荐

  1. Wtl之奇技淫巧篇:一、SDI如何居中显示视图

    Wtl的sdi应用,视图默认铺满框架的客户区.视图通常用modeless对话框,所有的界面元素都拥挤在左上角,这明显很丑陋.我们尝试让视图居中显示,保持原始大小,这是个很典型的问题,看似简单,诸多细节 ...

  2. Etl之HiveSql调优(设置map reduce 的数量)

    前言: 最近发现hivesql的执行速度特别慢,前面我们已经说明了left和union的优化,下面咱们分析一下增加或者减少reduce的数量来提升hsql的速度. 参考:http://www.cnbl ...

  3. 使用jQuery开发iOS风格的页面导航菜单

    在线演示1 本地下载     申请达人,去除赞助商链接 iOS风格的操作系统和导航方式现在越来越流行,在今天的jQuery教程中,我们将介绍如何生成一个iphone风格的菜单导航. HTML代码 我们 ...

  4. UNIX环境高级编程笔记之标准I/O库

    一.总结 文件I/O一章讲了不带缓冲的I/O,本章讲的是带缓冲的I/O.不带缓冲针对的是内核的系统调用,而带缓冲针对的是用户空间的标准库函数,是基于带缓冲的I/O实现的.不带缓冲的I/O通过文件描述符 ...

  5. Asp.net Request方法获取客户端的信息

    Response.Write("客户端计算机名:" + Request.UserHostName + "<BR />"); Response.Wri ...

  6. Android界面布局基本属性

    在 android 中我们常用的布局方式有这么几种:1.LinearLayout ( 线性布局 ) :(里面只可以有一个控件,并且不能设计这个控件的位置,控件会放到左上角)              ...

  7. csv大文件分割以及添加表头

    注:这里说的大文件也不是太大,只有60多M而已(70多万条数据),相对比较大而已. 为了减轻编辑的工作,某种情况下网站上可能用会到csv格式的文件进行数据导入,但一般网站除了有上传文件大小限制以外,还 ...

  8. ps图像渐变

    整理自:http://zhidao.baidu.com/question/16374167.html 1.用ps打开图片 2.在切换至英文输入法状态下(下面的操作均如此)按q 快捷键q的作用是切换标准 ...

  9. 【转】Velocity模板(VM)语言介绍

    http://www.blogjava.net/caizh2009/archive/2010/08/20/329495.html Velocity是什么? Velocity是一个基于java的模板引擎 ...

  10. C# 解析百度天气数据,Rss解析百度新闻以及根据IP获取所在城市

    百度天气 接口地址:http://api.map.baidu.com/telematics/v3/weather?location=上海&output=json&ak=hXWAgbsC ...