[luogu3385]dfs_spfa判负环模板
解题关键:模板保存。
判负环不需要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判负环模板的更多相关文章
- SPFA判负环模板
void DFS_SPFA(int u){ if(flag) return; vis[u]=true; for(int i=head[u];i;i=edges[i].nxt){ if(fl ...
- dfs_SPFA 判负环
感觉有点像tarjan求SCC #include <iostream> #include <cstdio> #include <algorithm> #includ ...
- poj3259 Wormholes (判负环)【spfa】(模板)
<题目链接> 题目大意: John的农场里N块地,M条路连接两块地,W个虫洞,虫洞是一条单向路,会在你离开之前把你传送到目的地,就是当你过去的时候时间会倒退Ts.我们的任务是知道会不会在从 ...
- [模板]SPFA判负环
目录 一.BFS法判负环 二.DFS法判负环 三.SPFA判正环 一.BFS法判负环 Code: #include<bits/stdc++.h> #define re register # ...
- Poj(3259),SPFA,判负环
题目链接:http://poj.org/problem?id=3259 Wormholes Time Limit: 2000MS Memory Limit: 65536K Total Submis ...
- poj3259(spfa判负环)
题目连接:http://poj.org/problem?id=3259 题意:John的农场里N块地,M条路连接两块地,W个虫洞,虫洞是一条单向路,会在你离开之前把你传送到目的地,就是当你过去的时候时 ...
- 浅谈SPFA判负环
目录 SPFA判负环 [前言] [不可代替性] [具体实现] SPFA的过程 判负环 [核心代码] [例题] SPFA判负环 有不足的地方请指出 本蒟蒻一定会修改吼 [前言] 最短路的求法中最广为人知 ...
- 【原创】SPFA判负环
[定义与概念] 给定一张有向图,若其中存在一个环的所有权值之和为负数,这个环称为负环. [算法实现] 当然,负环的求解可以暴搜,但是时间复杂度就难以入眼了,我们回到求解单源最短路径算法上面,看看它们能 ...
- SPFA算法的判负环问题(BFS与DFS实现)
经过笔者的多次实践(失败),在此温馨提示:用SPFA判负环时一定要特别小心! 首先SPFA有BFS和DFS两种实现方式,两者的判负环方式也是不同的. BFS是用一个num数组,num[x] ...
随机推荐
- JSON 在JavaScript 中的应用及自己的理解
[对象和json]JSON:JavaScript 对象表示法(JavaScript Object Notation).JSON 是存储和交换文本信息的语法.类似 XML.JSON是一种数据格式,不是一 ...
- Pycharm如何打断点
一. python代码的调试方式 1. 使用print语句打印出来 2. 在编辑工具中,加断点跟踪(打断点) 3. 使用日志模块,输出到日志中 下面我们来看一下如何打断点 二. 环境 python 3 ...
- (转)Java发送http请求(get 与post方法请求)
本文转载于:http://bijian1013.iteye.com/blog/2166855 package com.bijian.study; import java.io.BufferedRead ...
- 剑指offer--16.数组中重复的数字
时间限制:1秒 空间限制:32768K 热度指数:198342 本题知识点: 数组 题目描述 在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复 ...
- 20165210 Java第九周学习总结
20165210 Java第九周学习总结 教材学习内容 - 第十三章学习总结 URL类: URL的构造方法: try { URL url = new URL("http://www.goog ...
- C#异步编程(三)内核模式线程同步
其实,在开发过程中,无论是用户模式的同步构造还是内核模式,都应该尽量避免.因为线程同步都会造成阻塞,这就影响了我们的并发量,也影响整个应用的效率.不过有些情况,我们不得不进行线程同步. 内核模式 wi ...
- check: 获得所有呗选中的checked标签的元素值 mapArrayElement(arrEles)
首先引用: <script src="../js/myjs/mapArrayElement.js"></script> 然后在<javascript& ...
- [置顶]
从零制作文件系统到JZ2440,使其支持telnet , ftp 和tftp
转自:http://mp.weixin.qq.com/s?__biz=MzAxNTAyOTczMw==&mid=2649328515&idx=1&sn=5849fba4b44e ...
- 数据库:sql语句分别按日,按周,按月,按季统计金额
如: 表:consume_record 字段:consume (money类型) date (datetime类型) 请问怎么写四条sql语句分别按日,按周,按月,按季统计消费总量. 如:1月 120 ...
- 发任务找不到test-unit报错
发任务的时候因找不到gem包test-unit报错, 出错行: require 'test/unit' require 'test/unit/testresult' 解决办法如下 1.通过命令查看ge ...