Luogu P3385 【模板】负环

题目描述

暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索

输入输出格式

输入格式:

第一行一个正整数T表示数据组数,对于每组数据:

第一行两个正整数N M,表示图有N个顶点,M条边

接下来M行,每行三个整数a b w,表示a->b有一条权值为w的边(若w<0则为单向,否则双向)

输出格式:

共T行。对于每组数据,存在负环则输出一行"YE5"(不含引号),否则输出一行"N0"(不含引号)。

输入输出样例

输入样例#1: 复制
2
3 4
1 2 2
1 3 4
2 3 1
3 1 -3
3 3
1 2 3
2 3 4
3 1 -8
输出样例#1: 复制
N0
YE5

说明

N,M,|w|≤200 000;1≤a,b≤N;T≤10 建议复制输出格式中的字符串。

此题普通Bellman-Ford或BFS-SPFA会TLE

DFS版SPFA判负环,注意输出有坑点,输出YE5 和 N0 而不是 YES 和 NO

 1 //2018年3月4日22:19:48
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int N = 400001;
 9 const int M = 400001;
10 
11 struct Edge{
12     int len, to, nxt;
13 }E[M];
14 int fir[N], edge_num;
15 
16 void addEdge(int x, int y, int z){
17     E[++edge_num].to = y;
18     E[edge_num].len = z;
19     E[edge_num].nxt = fir[x];
20     fir[x] = edge_num;
21 }
22 
23 int T, n, m;
24 int dis[N], vis[N], flag;
25 void spfa(int A){
26     vis[A] = 1;
27     for(int i=fir[A]; i; i=E[i].nxt){
28         if(dis[E[i].to] > dis[A] + E[i].len){
29             if(vis[E[i].to] || flag){ flag = 1; break; }
30             dis[E[i].to] = dis[A] + E[i].len;
31             spfa(E[i].to);
32         }
33     }
34     vis[A] = 0;
35 }
36 
37 int main(){
38     scanf("%d", &T);
39     while(T--){
40         flag = 0;
41         memset(E, 0, sizeof(E)); edge_num = 0; memset(fir, 0, sizeof(fir));
42         scanf("%d%d", &n, &m);
43         for(int i=1; i<=m; i++){
44             int x, y, z;
45             scanf("%d%d%d", &x, &y, &z);
46             if(z >= 0){
47                 addEdge(x, y, z); addEdge(y, x, z);
48             }else addEdge(x, y, z);
49         }
50         for(int i=1; i<=n; i++){
51             spfa(i); if(flag) break;
52         }
53         if(flag) puts("YE5");
54         else puts("N0"); 
55     }
56 
57     return 0;
58 }
原文地址:https://www.cnblogs.com/sineagle/p/8506779.html