代码
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int N = 2e3 + 10, M = 1e4 + 10;
int n, m;
int head[N], e[M], ne[M], w[M], idx;
bool st[N];
int dist[N];
int cnt[N]; //cnt[x] 表示 当前从1-x的最短路的边数
void add(int a, int b, int c)
{
e[idx] = b;
ne[idx] = head[a];
w[idx] = c;
head[a] = idx++;
}
bool spfa(){
// 这里不需要初始化dist数组为 正无穷/初始化的原因是, 如果存在负环, 那么dist不管初始化为多少, 都会被更新
queue<int> q;
//不仅仅是1了, 因为点1可能到不了有负环的点, 因此把所有点都加入队列
for(int i=1;i<=n;i++){
q.push(i);
st[i]=true;
}
while(q.size()){
int t = q.front();
q.pop();
st[t]=false;
for(int i = head[t];i!=-1; i=ne[i]){
int j = e[i];
if(dist[j]>dist[t]+w[i]){
dist[j] = dist[t]+w[i];
cnt[j] = cnt[t]+1;
if(cnt[j]>=n){
return true;
}
if(!st[j]){
q.push(j);
st[j]=true;
}
}
}
}
return false;
}
int main()
{
cin >> n >> m;
memset(head, -1, sizeof head);
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
}
if (spfa()) {
cout << "Yes" << endl;
}
else {
cout << "No" << endl;
}
return 0;
}
请问不需要 memset(dist, 0x3f, sizeof dist); 初始化可不可以理解为因为本题需要判断负环,如果存在负环,那么就会导致松弛的时候,w[i] < 0,于是导致 dist 更新;而如果不存在负环,那么这种情况 dis 到底更不更新无所谓(其实dis不会更新吧,因为没有对 dis 初始化为无穷的话默认就是0, 0和一个正数比较肯定不需要松弛)
#include [HTML_REMOVED]
#include [HTML_REMOVED]
#include [HTML_REMOVED]
using namespace std;
const int N = 10010;
int w[N], h[N], e[N], ne[N], idx;
int d[N], cnt[N];
bool st[N];
int q[N];
int n, m;
void add(int a, int b, int c) {
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}
bool spfa() {
int hh = 0, tt = -1;
}
int main() {
cin >> n >> m;
memset(h, -1, sizeof(h));
}
我在这里使用了手写队列却ac不了,有大佬看看为什么吗…我直接用的上一题的模版
你这个手写队列初始化给的空间有问题,不应该是节点数N,而应该是N*M,因为要注意到手写队列的
tt
和hh
会一直右移,其需要的空间为可能通过的元素的总和。记录美好生活
为什么不初始化终于弄懂了,感谢大佬。
return false;会不会导致最后return的结果就是false啊
不会,如果cnt[j]>=n,就说明已经证明了存在负环,会直接跳出循环,不会执行下面的return false;
if(!st[j]){
q.push(j);
st[j]=true;
}
大佬这是啥意思啊
如果之前st[j]未在队列中,则将st[j]入队,并标记
结点只有弹出队列的时候才会标记false,结点在队列中时会被标记true。当我们遍历队头的所有出边时,如果遍历到了本来就在队列中的结点,我们不去让该结点再次入队,而只更新他的st值。
st更新没有必要 因为原先有过赋值true 节点一定要再次入列是因为 dist[j]如果变小但是j已经被淘汰了 未来这个j如果成为t的话 能让它指向的节点的dist值进行更新 就会改变指向节点的cnt数组的大小 因为有变动 所以一定要加入
if(cnt[j]>=n)
这一行可以只判断==吗?
可以的。
卡哇伊的二次元头像没了,爷青结