P3385 【模板】负环
2024年9月28日大约 3 分钟
P3385 【模板】负环
题目描述
给定一个
负环的定义是:一条边权之和为负数的回路。
输入格式
本题单测试点有多组测试数据。
输入的第一行是一个整数
第一行有两个整数,分别表示图的点数
接下来
- 若
,则表示存在一条从 至 边权为 的边,还存在一条从 至 边权为 的边。 - 若
,则只表示存在一条从 至 边权为 的边。
输出格式
对于每组数据,输出一行一个字符串,若所求负环存在,则输出 YES,否则输出 NO。
样例 #1
样例输入 #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
NO
YES提示
数据规模与约定
对于全部的测试点,保证:
, 。 , 。 。
提示
请注意,
思路
spfa判断负环
报错代码
#include <iostream>
#include <queue>
#include <vector>
#include <list>
using namespace std;
struct edge
{
int to;
int weight;
};
struct node
{
list<edge> edges;
};
struct graph
{
node nodes[2048];
int n;
graph(int n) : n(n) {}
void addedge(int start, int end, int weight)
{
nodes[start].edges.push_back({end, weight});
}
void spfa()
{
vector<int> dist(n, 0x3f3f3f3f);
dist[0] = 0;
vector<int> cnt(n, 0);
queue<int> que;
vector<int> visit(n,0);
// visit[0] = 1;
que.push(0);
while (!que.empty())
{
int now = que.front();
que.pop();
visit[now] = 0;
for (edge e : nodes[now].edges)
{
int end = e.to;
if (dist[end] > dist[now] + e.weight)
{
dist[end] = dist[now] + e.weight;
// cnt[end]++; // 这样判断存在bug
cnt[end] = cnt[now] + 1; // 最短路径长度
if (cnt[end] > n)
{
cout << "YES" << "\n";
return;
}
if (!visit[end])
{
que.push(end);
visit[end] = 1;
}
}
}
}
cout << "NO" << "\n";
}
};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
for (int p = 0; p < t; p++)
{
int n, m;
cin >> n >> m;
graph gra(n + 1);
int u, v, w;
for (int i = 0; i < m; i++)
{
cin >> u >> v >> w;
gra.addedge(u, v, w);
if (w >= 0)
{
gra.addedge(v, u, w);
}
}
for (int i = 1; i <= n; i++)
{
gra.addedge(0, i, 0);
// gra.addedge(i, 0, 0);
}
gra.spfa();
}
return 0;
}测试组#12一直过不去
1
4 3
2 3 -1
3 4 -1
4 2 -1read Y, expected N
2->3->4->2,应该是存在负环的
使用题解,发现ac了,题目测试点应该没问题 题解
再细想一下 题目要求提到是从1出发的负环,所以不用建立超级源点((+﹏+)~晕)
改完之后就可以AC了
题解
#include <iostream>
#include <queue>
#include <vector>
#include <list>
using namespace std;
struct edge
{
int to;
int weight;
};
struct node
{
list<edge> edges;
};
struct graph
{
node nodes[2048];
int n;
graph(int n) : n(n) {}
void addedge(int start, int end, int weight)
{
nodes[start].edges.push_back({end, weight});
}
void spfa()
{
vector<int> dist(n, 0x3f3f3f3f);
dist[1] = 0;
vector<int> cnt(n, 0);
queue<int> que;
vector<int> visit(n,0);
// visit[0] = 1;
que.push(1);
while (!que.empty())
{
int now = que.front();
que.pop();
visit[now] = 0;
for (edge e : nodes[now].edges)
{
int end = e.to;
if (dist[end] > dist[now] + e.weight)
{
dist[end] = dist[now] + e.weight;
// cnt[end]++; // 这样判断存在bug
cnt[end] = cnt[now] + 1; // 最短路径长度
if (cnt[end] > n)
{
cout << "YES" << "\n";
return;
}
if (!visit[end])
{
que.push(end);
visit[end] = 1;
}
}
}
}
cout << "NO" << "\n";
}
};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
for (int p = 0; p < t; p++)
{
int n, m;
cin >> n >> m;
graph gra(n + 1);
int u, v, w;
for (int i = 0; i < m; i++)
{
cin >> u >> v >> w;
gra.addedge(u, v, w);
if (w >= 0)
{
gra.addedge(v, u, w);
}
}
// 去掉超级源点
// for (int i = 1; i <= n; i++)
// {
// gra.addedge(0, i, 0);
// }
gra.spfa();
}
return 0;
}