图论-SPFA与差分约束

闻道有先后,术业有专攻

当用来判断负环的时候,SPFA 还挺好用的


int pre[N];
void print_path(int s, int t){
    if(s == t) {cout << s; return ;}
    print_path(s, pre[t]);
    cout <<" " << t;
}

int head[N], cnt;
struct Edge{
    int from, to, nxt, c;
}e[N << 1];
void add(int u, int v, int c){
    e[++cnt].from = u;
    e[cnt].to = v;
    e[cnt].nxt = head[u];
    head[u] = cnt;
    e[cnt].c = c;
}
int dis[N], Neg[N];
bool inq[N];
int spfa(int s){
    memset(Neg, 0, sizeof(Neg));
    Neg[s] = 1;
    for(int i = 1; i <= n; i++) dis[i] = 1e9, inq[i] = false;
    dis[s] = 0;
    queue<int> Q;
    Q.push(s);
    inq[s] = true;
    while(!Q.empty()){
        int u = Q.front(); Q.pop();
        inq[u] = false;
        for(int i = head[u]; i != 0; i = e[i].nxt){
            int v = e[i].to, c = e[i].c;
            if(dis[v] > dis[u] + c){
                dis[v] = dis[u] + c;
                pre[v] = u;
                if(!inq[v]){
                    inq[v] = true;
                    Q.push(v);
                    Neg[v]++;
                    if(Neg[v] > n){
                        return 1;
                    }
                }

            }
        }
    }
    return 0;
}

如果是差分约束系统的话,那么就先建超级源点 \(S_0\), 连接所有的点,且边权为 0

void solve() {
    cin >> n >> m;
    for(int i = 1; i <= n; i++) add(0, i, 0);
    for(int i = 1; i <= m; i++){
        int u, v, val;
        cin >> v >> u >> val;
        add(u, v, val);
    }
    if(spfa(0)) cout << "NO";
    else{
        for(int i = 1; i <= n; i++){
            cout << dis[i] << " ";
        }
    }
}
posted @ 2024-06-06 12:37  9102700  阅读(16)  评论(0)    收藏  举报