给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环, 边权可能为负数。
请你判断图中是否存在负权回路。
输入格式
第一行包含整数 n 和 m。
接下来 m 行每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。
输出格式
如果图中存在负权回路,则输出 Yes
,否则输出 No
。
数据范围
1≤n≤2000,
1≤m≤10000,
图中涉及边长绝对值均不超过 10000。
输入样例:
3 3
1 2 -1
2 3 4
3 1 -4
输出样例:
Yes
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;const int N = 10010;
int StartNode[N],Edgeto[N],NextNode[N],Weight[N];
int n,m,x,y,z,idx;
int dist[N],cnt[N],att[N];
queue<int> Q;void add(int x,int y,int z){Edgeto[idx] = y;Weight[idx] = z;NextNode[idx] = StartNode[x];StartNode[x] = idx;idx ++;
}int spfa(){memset(dist,0x3f,sizeof dist);for(int i = 0;i <= n;i++){Q.push(i);att[i] = 1;}while(Q.size()!=0){int now = Q.front();Q.pop();att[now] = 0;for(int i = StartNode[now];i != -1;i = NextNode[i]){int j = Edgeto[i];if(dist[j] > dist[now] + Weight[i]){dist[j] = dist[now] + Weight[i];cnt[j] = cnt[now] + 1;if(cnt[j] > n){return 1;}if(att[j] == 0){Q.push(j);att[j] = 1;}}}}return 0;
}int main(){cin>>n>>m;memset(StartNode,-1,sizeof StartNode);memset(cnt,0,sizeof cnt);while(m--){cin>>x>>y>>z;add(x,y,z);}int res = spfa();if(res == 1){cout<<"Yes";}else{cout<<"No";}return 0;
}