BZOJ1715 SPFA 浅谈图论之负环的多重化判定
来源:互联网 发布:英语句子成分解析软件 编辑:程序博客网 时间:2024/05/18 02:06
大家都很强, 可与之共勉 。
我们拿BZOJ1715做一个例子。
题目很简单,就是要判是否存在负环。
注意加边的时候要正边权加双向边。
主要探讨一下几种写法的各自优秀之处
BFS版:
速度随机化起点后在72ms左右
判入队次数是否大于n次
如果是,则存在负环
/************************************************************** Problem: 1715 User: Lazer2001 Language: C++ Result: Accepted Time:72 ms Memory:1376 kb****************************************************************/# include <bits/stdc++.h>inline bool chkmin ( int& d, const int& x ) { return ( d > x ) ? d = x, 1 : 0 ;}struct edge { int to, w ; edge* nxt ;} g [6456], *NewEdge, *head [567] ;inline int add_edge ( int u, int v, int w ) { *( ++ NewEdge ) = ( edge ) { v, w, head [u] } ; head [u] = NewEdge ;}std :: queue < int > Q ;int cnt [567] ;int dis [567] ;bool inq [567] ;bool Spfa ( int S, int N ) { memset ( cnt, 0, sizeof cnt ) ; memset ( inq, 0, sizeof inq ) ; memset ( dis, 0x3f, sizeof dis ) ; while ( ! Q.empty ( ) ) Q.pop ( ) ; Q.push ( S ) ; dis [S] = 0 ; inq [S] = 1 ; cnt [S] = 1 ; while ( ! Q.empty ( ) ) { int u = Q.front ( ) ; Q.pop ( ) ; inq [u] = 0 ; for ( edge* it = head [u] ; it ; it = it -> nxt ) { if ( chkmin ( dis [it -> to], dis [u] + it -> w ) ) { if ( ! inq [it -> to] ) { Q.push ( it -> to ) ; if ( ++ cnt [it -> to] > N ) return true ; } } } } return false ;}int main ( ) { srand ( 20010608 ) ; int T ; scanf ( "%d", & T ) ; while ( T -- ) { NewEdge = g ; memset ( head, 0, sizeof head ) ; int n, m, o ; scanf ( "%d%d%d", & n, & m, & o ) ; while ( m -- ) { int u, v, w ; scanf ( "%d%d%d", & u, & v, & w ) ; add_edge ( u, v, w ) ; add_edge ( v, u, w ) ; // 这是什么设定!!! Why Double ??? } while ( o -- ) { int u, v, w ; scanf ( "%d%d%d", & u, & v, & w ) ; add_edge ( u, v, -w ) ; } int s = ( ( rand ( ) << 15 ) | rand ( ) ) % n + 1 ; puts ( Spfa ( 1, n ) ? "YES" : "NO" ) ; }}
DFS坑爹版
速度在430ms左右
/************************************************************** Problem: 1715 User: Lazer2001 Language: C++ Result: Accepted Time:432 ms Memory:1372 kb****************************************************************/# include <bits/stdc++.h>inline bool chkmin ( int& d, const int& x ) { return ( d > x ) ? d = x, 1 : 0 ;}struct edge { int to, w ; edge* nxt ;} g [6456], *NewEdge, *head [567] ;inline int add_edge ( int u, int v, int w ) { *( ++ NewEdge ) = ( edge ) { v, w, head [u] } ; head [u] = NewEdge ;}std :: queue < int > Q ;int dis [567] ;bool vis [567] ;inline bool spfa ( int u ) { vis [u] = 1 ; for ( edge* it = head [u] ; it ; it = it -> nxt ) { if ( chkmin ( dis [it -> to], dis [u] + it -> w ) ) { if ( vis [it -> to] ) return true ; if ( spfa ( it -> to ) ) return true ; } } return vis [u] = 0 ;}bool Spfa ( int n ) { memset ( vis, 0, sizeof vis ) ; memset ( dis, 0x3f, sizeof dis ) ;// static int seq [567] ;// for ( int i = 1 ; i <= n ; ++ i ) seq [i] = i ;// std :: random_shuffle ( seq + 1, seq + 1 + n ) ; for ( int i = 1 ; i <= n ; ++ i ) { dis [i] = 0 ; if ( spfa ( i ) ) return true ; } return false ;}int main ( ) { int T ; scanf ( "%d", & T ) ; while ( T -- ) { NewEdge = g ; memset ( head, 0, sizeof head ) ; int n, m, o ; scanf ( "%d%d%d", & n, & m, & o ) ; while ( m -- ) { int u, v, w ; scanf ( "%d%d%d", & u, & v, & w ) ; add_edge ( u, v, w ) ; add_edge ( v, u, w ) ; // 这是什么设定!!! Why Double ??? } while ( o -- ) { int u, v, w ; scanf ( "%d%d%d", & u, & v, & w ) ; add_edge ( u, v, -w ) ; } puts ( Spfa ( n ) ? "YES" : "NO" ) ; }}
为什么慢???
因为这个写法太不优秀了,会重复搜索
改成这样:
inline bool spfa ( int u ) { vis [u] = 1 ; for ( edge* it = head [u] ; it ; it = it -> nxt ) { if ( chkmin ( dis [it -> to], dis [u] + it -> w ) ) { if ( vis [it -> to] ) return true ; if ( spfa ( it -> to ) ) return true ; } } return vis [u] = 0 ;}bool Spfa ( int n ) { for ( int i = 1 ; i <= n ; ++ i ) { memset ( vis, 0, sizeof vis ) ; memset ( dis, 0, sizeof dis ) ; if ( spfa ( i ) ) return true ; } return false ;}
因为是判负环,所以我们更本不需要处理dis数组,不需要求出具体的值,直接全为某一个数就好,这样更新次数少了很多,不需要把dis[起点]赋成0
/************************************************************** Problem: 1715 User: Lazer2001 Language: C++ Result: Accepted Time:32 ms Memory:1372 kb****************************************************************/# include <bits/stdc++.h>inline bool chkmin ( int& d, const int& x ) { return ( d > x ) ? d = x, 1 : 0 ;}struct edge { int to, w ; edge* nxt ;} g [6456], *NewEdge, *head [567] ;inline int add_edge ( int u, int v, int w ) { *( ++ NewEdge ) = ( edge ) { v, w, head [u] } ; head [u] = NewEdge ;}std :: queue < int > Q ;int dis [567] ;bool vis [567] ;inline bool spfa ( int u ) { vis [u] = 1 ; for ( edge* it = head [u] ; it ; it = it -> nxt ) { if ( chkmin ( dis [it -> to], dis [u] + it -> w ) ) { if ( vis [it -> to] ) return true ; if ( spfa ( it -> to ) ) return true ; } } return vis [u] = 0 ;}bool Spfa ( int n ) { for ( int i = 1 ; i <= n ; ++ i ) { memset ( vis, 0, sizeof vis ) ; memset ( dis, 0, sizeof dis ) ; if ( spfa ( i ) ) return true ; } return false ;}int main ( ) { int T ; scanf ( "%d", & T ) ; while ( T -- ) { NewEdge = g ; memset ( head, 0, sizeof head ) ; int n, m, o ; scanf ( "%d%d%d", & n, & m, & o ) ; while ( m -- ) { int u, v, w ; scanf ( "%d%d%d", & u, & v, & w ) ; add_edge ( u, v, w ) ; add_edge ( v, u, w ) ; // 这是什么设定!!! Why Double ??? } while ( o -- ) { int u, v, w ; scanf ( "%d%d%d", & u, & v, & w ) ; add_edge ( u, v, -w ) ; } puts ( Spfa ( n ) ? "YES" : "NO" ) ; }}
代码2:
/************************************************************** Problem: 1715 User: Lazer2001 Language: C++ Result: Accepted Time:32 ms Memory:1372 kb****************************************************************/# include <bits/stdc++.h>inline bool chkmin ( int& d, const int& x ) { return ( d > x ) ? d = x, 1 : 0 ;}struct edge { int to, w ; edge* nxt ;} g [6456], *NewEdge, *head [567] ;inline int add_edge ( int u, int v, int w ) { *( ++ NewEdge ) = ( edge ) { v, w, head [u] } ; head [u] = NewEdge ;}std :: queue < int > Q ;int dis [567] ;bool vis [567] ;inline bool spfa ( int u ) { vis [u] = 1 ; for ( edge* it = head [u] ; it ; it = it -> nxt ) { if ( chkmin ( dis [it -> to], dis [u] + it -> w ) ) { if ( vis [it -> to] ) return true ; if ( spfa ( it -> to ) ) return true ; } } return vis [u] = 0 ;}bool Spfa ( int n ) { memset ( vis, 0, sizeof vis ) ; memset ( dis, 0, sizeof dis ) ; for ( int i = 1 ; i <= n ; ++ i ) { if ( spfa ( i ) ) return true ; } return false ;}int main ( ) { int T ; scanf ( "%d", & T ) ; while ( T -- ) { NewEdge = g ; memset ( head, 0, sizeof head ) ; int n, m, o ; scanf ( "%d%d%d", & n, & m, & o ) ; while ( m -- ) { int u, v, w ; scanf ( "%d%d%d", & u, & v, & w ) ; add_edge ( u, v, w ) ; add_edge ( v, u, w ) ; // 这是什么设定!!! Why Double ??? } while ( o -- ) { int u, v, w ; scanf ( "%d%d%d", & u, & v, & w ) ; add_edge ( u, v, -w ) ; } puts ( Spfa ( n ) ? "YES" : "NO" ) ; }}
所以后两种写法是优秀的。
阅读全文
0 0
- BZOJ1715 SPFA 浅谈图论之负环的多重化判定
- spfa判断负环
- spfa && 判断负环
- spfa负环 P2868
- 最短路之 SPFA(判环+负权)
- poj3259 Wormholes 图的负权回路判定,Bellman_Ford
- SPFA查找负环 POJ3259
- poj1860 spfa判断负环
- Wormholes(spfa判断负环)
- 关于spfa 判断负环
- 用SPFA判断负环的方法及其优化
- POJ3259_通过SPFA算法计算负环的裸体
- Bellman_ford或spfa 判断图是否存在负环
- BZOJ1715: [Usaco2006 Dec]Wormholes 虫洞 spfa 求负环
- bzoj1715 [Usaco2006 Dec]Wormholes 虫洞 spfa
- POJ 3259:Wormholes bellman_ford判定负环
- LightOJ 1074 - Extended Traffic (SPFA负环)
- POJ:3259 Wormholes(SPFA判断负环)
- HDU 4313 最小生成树
- 问题:使用docker时报错“net/http: TLS handshake timeout”的解决方案
- 3dsMax2018 SDK配置以及PluginWizard目标平台版本错误解决
- Spring配置文件xml约束出错
- c语言的数算据类型、运算符与表达式
- BZOJ1715 SPFA 浅谈图论之负环的多重化判定
- django 事务
- 使用C语言将pcm数据封装成wav文件
- DeepFace介绍
- Oracle数据库连接错误:ORA-12541:TNS:无监听程序
- 生成共用的一个Fragment
- linux 下maven安装
- 香港科技大学TensorFlow机器学习课程分享
- HYSBZ3676-回文串