解题关键:模板保存。

判负环不需要memset dis数组,因为已经更新过得d数组一定小于0,如果当前点可以更新d,说明d更小,有可能继续扩大负环,所以继续更新;如果比d[v]大,则不可能继续更新负环,所以直接终止。

 有向图只扫一个点貌似不可以。。。bfs_spfa的时候一定注意,但dfs_spfa一定可以。

dfs过不了这道题,因为必须经过1这个点,或许d不置0可以,但会超时?

有向图可以使用拓扑排序找环。

1、dfs

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
const int inf=0x3f3f3f3f;
const int maxm=;
const int maxn=;
int head[maxn],tot,n,m;
struct edge{
int to;
int w;
int nxt;
}e[maxm];
void add_edge(int u,int v,int w){
e[tot].w=w;
e[tot].to=v;
e[tot].nxt=head[u];
head[u]=tot++;
}
bool vis[maxn];
int d[maxn];
//
bool dfs_spfa(int u){
vis[u]=;
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
if(d[v]>d[u]+e[i].w){
d[v]=d[u]+e[i].w;
if(vis[v]||dfs_spfa(v)) return ;
}
}
vis[u]=;
return ;
}
int main(){
int a,b,c,T;
scanf("%d",&T);
while(T--){
tot=;
memset(head,-,sizeof head);
memset(vis,,sizeof vis);
memset(d,,sizeof d);
scanf("%d%d",&n,&m);
for(int i=;i<m;i++){//注意为双向边
scanf("%d%d%d",&a,&b,&c);
if(c<) add_edge(a,b,c);
else add_edge(a,b,c),add_edge(b,a,c);
}
bool flag=false;
for(int i=;i<=n;i++){
if(dfs_spfa(i)){
flag=true;
break;
}
}
if(flag) puts("YE5");
else puts("N0");
}
return ;
}

2、bfs_spfa

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxm=;
const int maxn=;
int head[maxn],tot,n,m,cnt[maxn],w;
struct edge{
int to;
int w;
int nxt;
}e[maxm];
void add_edge(int u,int v,int w){
e[tot].w=w;
e[tot].to=v;
e[tot].nxt=head[u];
head[u]=tot++;
} bool vis[maxn];
queue<int>que;//队列是点的队列
int d[maxn];
bool spfa(int s){
memset(cnt,,sizeof cnt);
fill(d+,d+n+,inf);
memset(vis,,sizeof vis);
while(!que.empty()) que.pop();
que.push(s);
vis[s]=true;
d[s]=;
while (!que.empty()){
int u=que.front();
que.pop();
vis[u]=false;
for (int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
int w=e[i].w;
if (d[v]>d[u]+w){
d[v]=d[u]+w;
cnt[v]=cnt[u]+;
if(cnt[v]>n) return true;
if (!vis[v]){
vis[v]=true;
que.push(v);
}
}
}
}
return false;
}
int main(){
int a,b,c,T;
scanf("%d",&T);
while(T--){
tot=;
memset(head,-,sizeof head);
memset(vis,,sizeof vis);
memset(d,,sizeof d);
scanf("%d%d",&n,&m);
for(int i=;i<m;i++){//注意为双向边
scanf("%d%d%d",&a,&b,&c);
add_edge(a,b,c);
if(c>=)add_edge(b,a,c);
}
if(spfa()) puts("YE5");
else puts("N0");
}
return ;
}

3、bfs_spfa(num>n)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxm=;
const int maxn=;
int head[maxn],tot,n,m,num[maxn],w;
struct edge{
int to;
int w;
int nxt;
}e[maxm];
void add_edge(int u,int v,int w){
e[tot].w=w;
e[tot].to=v;
e[tot].nxt=head[u];
head[u]=tot++;
} bool vis[maxn];
queue<int>que;//队列是点的队列
int d[maxn];
bool spfa(int s){
memset(num,,sizeof num);
fill(d+,d+n+,inf);
memset(vis,,sizeof vis);
while(!que.empty()) que.pop();
que.push(s);
vis[s]=true;
d[s]=;
while (!que.empty()){
int u=que.front();
que.pop();
vis[u]=false;
for (int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
int w=e[i].w;
if (d[v]>d[u]+w){
d[v]=d[u]+w;
if (!vis[v]){
vis[v]=true;
que.push(v);//hash一下,可判断是否存在负环
num[v]++;
if(num[v]>n) return true;
}
}
}
}
return false;
}
int main(){
int a,b,c,T;
scanf("%d",&T);
while(T--){
tot=;
memset(head,-,sizeof head);
memset(vis,,sizeof vis);
memset(d,,sizeof d);
scanf("%d%d",&n,&m);
for(int i=;i<m;i++){//注意为双向边
scanf("%d%d%d",&a,&b,&c);
add_edge(a,b,c);
if(c>=)add_edge(b,a,c);
}
if(spfa()) puts("YE5");
else puts("N0");
}
return ;
}

[luogu3385]dfs_spfa判负环模板的更多相关文章

  1. SPFA判负环模板

    void DFS_SPFA(int u){   if(flag) return; vis[u]=true;   for(int i=head[u];i;i=edges[i].nxt){   if(fl ...

  2. dfs_SPFA 判负环

    感觉有点像tarjan求SCC #include <iostream> #include <cstdio> #include <algorithm> #includ ...

  3. poj3259 Wormholes (判负环)【spfa】(模板)

    <题目链接> 题目大意: John的农场里N块地,M条路连接两块地,W个虫洞,虫洞是一条单向路,会在你离开之前把你传送到目的地,就是当你过去的时候时间会倒退Ts.我们的任务是知道会不会在从 ...

  4. [模板]SPFA判负环

    目录 一.BFS法判负环 二.DFS法判负环 三.SPFA判正环 一.BFS法判负环 Code: #include<bits/stdc++.h> #define re register # ...

  5. Poj(3259),SPFA,判负环

    题目链接:http://poj.org/problem?id=3259 Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submis ...

  6. poj3259(spfa判负环)

    题目连接:http://poj.org/problem?id=3259 题意:John的农场里N块地,M条路连接两块地,W个虫洞,虫洞是一条单向路,会在你离开之前把你传送到目的地,就是当你过去的时候时 ...

  7. 浅谈SPFA判负环

    目录 SPFA判负环 [前言] [不可代替性] [具体实现] SPFA的过程 判负环 [核心代码] [例题] SPFA判负环 有不足的地方请指出 本蒟蒻一定会修改吼 [前言] 最短路的求法中最广为人知 ...

  8. 【原创】SPFA判负环

    [定义与概念] 给定一张有向图,若其中存在一个环的所有权值之和为负数,这个环称为负环. [算法实现] 当然,负环的求解可以暴搜,但是时间复杂度就难以入眼了,我们回到求解单源最短路径算法上面,看看它们能 ...

  9. SPFA算法的判负环问题(BFS与DFS实现)

    经过笔者的多次实践(失败),在此温馨提示:用SPFA判负环时一定要特别小心! 首先SPFA有BFS和DFS两种实现方式,两者的判负环方式也是不同的.       BFS是用一个num数组,num[x] ...

随机推荐

  1. Python入门及安装

    简介 是用来编写应用程序的高级编程语言,"内置电池",哲学:简单优雅,尽量写容易看明白的代码,尽量写少的代码,适合干嘛:网络应用.网站.后台服务:日常些工具,如系统管理员需要的脚本 ...

  2. P1216 [IOI1994][USACO1.5]数字三角形 Number Triangles

    P1216 [IOI1994][USACO1.5]数字三角形 Number Triangles 这个题吧,之前学DP的时候就做过一次了,其实还是挺简单的,如果一步一步按照找状态定义,找边界条件,找转移 ...

  3. hzau 1205 Sequence Number(二分)

    G. Sequence Number In Linear algebra, we have learned the definition of inversion number: Assuming A ...

  4. 你妹的IOS7

    第一时间升级到了IOS7,想体验一把,界面卡就算了,付费的软件闪退也就罢了,耗电发烫也算球了!你妹的,连个电话都打不了了,刚说几句话就黑屏了,要你还有啥用了,果断降级,IOS6已经下载完了,刷机去!

  5. Win7+VS2010下配置WTL开发环境

    一.今天Win7下刚装了VS2010,解压wtl81_12085.zip到C盘根目录,进入C:\wtl81_12085\AppWiz下,执行setup100.js提示向导安装成功. 在VS2010中新 ...

  6. /var/adm/wtmp文件太大该怎么办?

    /var/admin/wtmp文件记录所有用户的登陆信息,随着时间会增长到很大,/var/adm/wtmp文件太大该怎么办呢?先来看看/var/adm/wtmp文件的属性:testterm1:/#ls ...

  7. atom总结

    window 系统 //查找 apm search emmet //安装 apm install emmet //删除  apm remove emmet

  8. c++primer 第二章编程练习答案

    2.7.1 #include<iostream> int main() { using namespace std; ]; ]; cout << "input nam ...

  9. 1150 Travelling Salesman Problem(25 分)

    The "travelling salesman problem" asks the following question: "Given a list of citie ...

  10. C#异步编程(四)混合模式线程同步

    之前讨论了基元用户模式和内核模式线程同步构造.其他所有线程同步构造都基于它们,而且一般都合并了用户模式和内核模式构造,我们称为混合线程同步构造.没有线程竞争时,混合构造提供了基元用户模式构造所具有的性 ...