[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\leq 2000n≤2000m\leq 3000m≤3000-10000\leq w\leq 10000−10000≤w≤10000T\leq 10T≤10
建议复制输出格式中的字符串。
code
//T到MMP...实测INF不设成10000绝对T //深吸一口氧 #include<queue> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; const int INF = 10000; const int MAXN = 30000; int T, n, m; int head[MAXN * 2], tot = 0; int dis[MAXN], cnt[MAXN]; bool vis[MAXN]; struct Edge { int node, next, value; }e[MAXN]; inline int read() { int num = 0, f = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); } while (isdigit(ch)) { num = num * 10 + ch - '0'; ch = getchar(); } return num * f; } void Add_Edge(int x, int y, int w) { e[++tot].node = y; e[tot].value = w; e[tot].next = head[x]; head[x] = tot; } bool SPFA(int s) { queue<int> q; memset(dis, INF, sizeof(dis)); memset(vis, false, sizeof(vis)); memset(cnt, 0, sizeof(cnt)); dis[s] = 0; vis[s] = true; cnt[s] = 1; q.push(s); while (!q.empty()) { int h = q.front(); q.pop(); vis[h] = false; for (int i = head[h], v; ~i, v = e[i].node; i = e[i].next) { if (dis[h] + e[i].value < dis[v]) { if (++ cnt[v] >= n) return true; dis[v] = dis[h] + e[i].value; if (!vis[v]) { q.push(v); vis[v] = true; } } } } return false; } int main() { T = read(); while (T --) { tot = 0; memset(head, -1, sizeof(head)); n = read(); m = read(); for (int i = 1; i <= m; ++ i) { int x = read(), y = read(), w = read(); Add_Edge(x, y, w); if (w >= 0) Add_Edge(y, x, w); } if(SPFA(1)) printf("YE5\n"); else printf("N0\n"); } return 0; }