负环?是有负权边的环还是一个边权之和为负的环?
还没有准确的定义(那就先忽略吧qwq
判断负环的方法:
暴力枚举/spfa/mellman—ford/奇怪的贪心/超神的搜索
可惜我只会spfa
spfa:垂死病中惊坐起
有两种spfa可以用来求负环:dfs和bfs
在求负环上bfs要更好一些,dfs稍逊色一些
(注意:要memset,变量类型定义的时候要细致一些)
//bfs版spfa
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long
using namespace std;
inline ll read()
{
ll sum = 0, p = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-')
p = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
(sum *= 10) += ch - '0';
ch = getchar();
}
return sum * p;
}
const int maxn = 2005,maxm = 3005;
struct edge
{
int nxt,to;
ll wei;
} e[maxm * 2];
int t,n,m,tot,cnt[maxn],head[maxn],dis[maxn];
bool vis[maxn];
void add(int a,int b,ll c)
{
e[++tot].nxt = head[a];
e[tot].to = b;
e[tot].wei = c;
head[a] = tot;
}
bool spfa(int x)
{
queue<int> q;
for(int i = 1; i <= n; i++)
dis[i] = 1e9;
vis[x] = true;
q.push(x);
cnt[x]++;
dis[x] = 0;
while(!q.empty())
{
int u = q.front();
q.pop();
vis[u] = false;
if(cnt[u] >= n)
return true;
for(int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if(dis[v] > dis[u] + e[i].wei)
{
dis[v] = dis[u] + e[i].wei;
if(!vis[v])
{
vis[v] = true;
q.push(v);
cnt[v] ++;
if(cnt[v] >= n)
return true;
}
}
}
}
return false;
}
int main()
{
t = read();
while(t--)
{
n = read(),m = read();
tot = 0;
memset(e,0,sizeof(e));
memset(dis,0,sizeof(dis));
memset(head,0,sizeof(head));
memset(vis,false,sizeof(vis));
memset(cnt,0,sizeof(cnt));
int a,b,c;
for(int i = 1; i <= m; i++)
{
a = read(),b = read(),c = read();
add(a,b,c);
if(c >= 0)
add(b,a,c);
}
if(spfa(1))
printf("YE5
");
else
printf("N0
");
}
return 0;
}
//dfs版spfa #include<cstdio> #include<algorithm> #include<cstring> using namespace std; inline int read() { int sum = 0, p = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') p = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (sum *= 10) += ch - '0'; ch = getchar(); } return sum * p; } const int maxn = 2005,maxm = 3005; bool flag,vis[maxn]; int n,m,t; int head[maxn],dis[maxn],cnt; struct edge { int nxt,to,wei; }e[maxm * 2]; void add(int a,int b,int c) { e[++cnt].nxt = head[a]; e[cnt].to = b; e[cnt].wei = c; head[a] = cnt; } void spfa(int x) { vis[x] = true; for(int i = head[x];i;i = e[i].nxt) { int v = e[i].to; if(dis[v] > dis[x] +e[i].wei) { if(vis[v] || flag) { flag = true; break; } dis[v] = dis[x] +e[i].wei; spfa(v); } } vis[x] = false; } int main() { t = read(); while(t--) { cnt = 0; flag = 0; memset(head,0,sizeof(head)); memset(dis,0,sizeof(dis)); memset(e,0,sizeof(e)); memset(vis,false,sizeof(vis)); n = read(),m = read(); int a,b,c; for(int i = 1;i <= m;i++) { a = read(),b = read(),c = read(); add(a,b,c); if(c >= 0) add(b,a,c); } for(int i = 1;i <= n;i++) { spfa(i); if(flag) break; } if(flag) printf("YE5 "); else printf("N0 "); } return 0; }