MnZn刚学SPFA,过了但不理解
查看原帖
MnZn刚学SPFA,过了但不理解
510555
ImposterAnYu楼主2024/10/3 22:13

RT,蒟蒻做完本题后去做了一道站外题,该站外题除 n,mn,m 分别扩大到了 <500<500<5000<5000 以外和本题没有任何区别。

#include <bits/stdc++.h>
#define N 500
#define M 12000
#define INF 1145141919810114514
#define int1 long long
using namespace std;
int1 t,n,m,x,y,z,i;
bool inq[N + 5];
int1 cnt[N + 5],dis[N + 5];
int1 hea[N + 5],nex[M + 5],to[M + 5],w[M + 5],bs;
int1 read(){
	int1 x = 0,f = 1;
	char ch = getchar();
	while(!isdigit(ch)){
		if(ch == '-'){
			f = -1;
		}
		ch = getchar();
	}
	while(isdigit(ch)){
		x = (x << 1) + (x << 3) + (ch ^ '0');
		ch = getchar();
	}
	return x * f;
}
char getc(int1 x){//1:数字    2:小写    4:大写    8:字符    16:空格
	char ch = getchar();
	while(!(((x & 1) && ch >= '0' && ch <= '9') || ((x & 2) && ch >= 'a' && ch <= 'z') || 
	((x & 4) && ch >= 'A' && ch <= 'Z') || ((x & 8) && ch != ' ' && ch != '\n' && ch != '\0') || ((x & 16) && ch != '\n' && ch != '\0'))){
		ch = getchar();
	}
	return ch;
}
void uprint(int1 x){
  	if(x > 9){
    	uprint(x / 10);
  	}
  	putchar(x % 10 ^ 48);
  	return ;
}
void print(int1 x){
  	if(x < 0){
    	putchar('-');
    	x = -x;
	}
	uprint(x);
	return ;
}
void ps(int1 x){
	print(x);
	putchar(' ');
	return ;
}
void pe(int1 x){
	print(x);
	putchar('\n');
	return ;
}
void add_edge(int1 x,int1 y,int1 z){
	nex[++bs] = hea[x],hea[x] = bs,to[bs] = y,w[bs] = z;
	return ;
}
bool solve(){
    n = read() + 1,m = read();
    for(i = 1; i <= m; i++){
        x = read() - 1,y = read(),z = read();
        add_edge(x,y,z);
        add_edge(y,x,-z);
    }
    for(i = 0; i < n; i++){
        cnt[i] = 0,dis[i] = -INF,inq[i] = 0;
        add_edge(n,i,0);
    }
    queue<int1> q;
    dis[n] = 0;
    inq[n] = 1;
    q.push(n);
    while(!q.empty()){
        int1 now = q.front();
        q.pop();
        inq[now] = 0;
        for(int1 i = hea[now]; i; i = nex[i]){
            int1 nxt = to[i];
            if(dis[now] + w[i] > dis[nxt]){
                dis[nxt] = dis[now] + w[i];
                cnt[nxt] = cnt[now] + 1;
                if(cnt[nxt] >= n){
                    return 0;
                }
                if(!inq[nxt]){
                    //inq[nxt] = 1;
                    q.push(nxt);
                }
            }
        }
    }
    return 1;
}
int main(){
	t = read();
    while(t--){
        bs = 0;
        for(i = 0; i <= n; i++){
            hea[i] = 0;
        }
        if(solve()){
            printf("true\n");
        }else{
            printf("false\n");
        }
    }
	return 0;
}

注意到SPFA中有一行注释(节点入队时打标记),这理应是SPFA中的关键代码(吧?),但是我的代码加上这一行会T得很惨,去掉这一行反而能AC……

(不过无论我的代码里有没有这一行,都能AC本题)

所以这到底是为什么啊qaq

2024/10/3 22:13
加载中...