解题关键:模板保存。

判负环不需要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. webdriver处理鼠标右键菜单栏

    selenium中ActionChains类提供了鼠标操作的常用方法,但对于鼠标右键的菜单栏,无论是send_keys(Keys.ARROW_DOWN)还是send_keys("K" ...

  2. BW信息STMS传输

    项目时先接过来的.前面的人建了很多数据源,信息对象.我也建了不少.最后分成三个包.非常混乱,信息对象不在一个包里.导入报错.先后顺序也没有逻辑.可为难我了. 本来想着是全部释放掉,然后在传输连接收集自 ...

  3. vue自定义全局组件(自定义插件)

    有时候我们在做开发的时候,就想自己写一个插件然后就可以使用自己的插件,那种成就感很强.博主最近研究element-ui和axios的时候,发现他们是自定义组件,但是唯一有一点不同的是,在用elemen ...

  4. 逻辑斯蒂(logistic)回归深入理解、阐述与实现

    第一节中说了,logistic 回归和线性回归的区别是:线性回归是根据样本X各个维度的Xi的线性叠加(线性叠加的权重系数wi就是模型的参数)来得到预测值的Y,然后最小化所有的样本预测值Y与真实值y'的 ...

  5. BitmapUtil(高效压缩不失真)

    package com.changim.patient.app.utils; import android.app.Activity; import android.content.ContentRe ...

  6. hdoj-3342-Legal or Not(拓扑排序)

    题目链接 /* Name:hdoj-3342-Legal or Not Copyright: Author: Date: 2018/4/11 15:59:18 Description: 判断是否存在环 ...

  7. msyql中myism和innodb的区别

    MyISAM存储引擎 MyISAM是 默认存储引擎.它基于更老的ISAM代码,但有很多有用的扩展.MyISAM存储引擎的一些特征: ●所有数据值先存储低字节.这使得数据机和操作系统分离.二进制轻便性的 ...

  8. string容器

    一.string特性 string是STL的字符串类型,通常用来表示字符串.而在使用string之前,字符串通常是用char*表示的,string与char*都可以用来表示字符串. 说到string的 ...

  9. 执行.class文件

    java packageName.className即可 但是注意,如果是有包的,这段指令一定是packageName的上层目录(即bin目录)执行!

  10. Linux评估 CPU使用情况

    评价参数 1)CPU utilization:最直观最重要的就是CPU的使用率.如果长期超过80%,则表明CPU遇到了瓶颈:2)User time: 用户进程使用的CPU:该数值越高越好,表明越多的C ...