负环、差分约束和传递闭包

负环

判负环:如果 n1 次之后依然存在可以松弛的边,那么就是存在负环。(负环永远可以松弛)

对于 spfa:看看有没有哪个元素入队 n 次。

代码:(有负环 YES,否则 NO)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define f(i, a, b) for(int i = (a); i <= (b); i++)
#define cl(i, n) i.clear(),i.resize(n);
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 1e9;
void cmax(int &x, int y) {if(x < y) x = y;}
void cmin(int &x, int y) {if(x > y) x = y;}
vector<pii> g[2010];int n, m; 
int dis[2010];
const int v = 10000;
void bellman_ford() {
    f(i, 1, n - 1) {
        f(j, 1, n) {
            for(pii kw : g[j]) {
                int k = kw.first, w = kw.second;
                if(dis[k] > dis[j] + w) {
                    dis[k] = dis[j] + w;
                }
            }
        }
    }
    f(j, 1, n) {
        for(pii kw : g[j]) {
            int k = kw.first, w = kw.second;
            if(dis[k] > dis[j] + w) {
                cout << "YES\n";
                return;
            }
        }
    }
    cout << "NO\n";
    return;
}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(NULL);
    cout.tie(NULL);
    //time_t start = clock();
    //think twice,code once.
    //think once,debug forever.
    int T; cin >> T;
    while(T--) {
        cin >> n >> m;
        f(i, 1, n) g[i].clear();
        f(i, 1, m) {
            int u, v, w; cin >> u >> v >> w;
            if(w < 0) {
                g[u].push_back({v, w});
            }
            else {
                g[v].push_back({u, w});
                g[u].push_back({v, w});
            }
        }  
        f(i, 1, n) dis[i] = inf;
        dis[1] = 0;
        bellman_ford();
    }
    //time_t finish = clock();
    //cout << "time used:" << (finish-start) * 1.0 / CLOCKS_PER_SEC <<"s"<< endl;
    return 0;
}

差分约束

差分约束系统 是一种特殊的 n 元一次不等式组,它包含 n 个变量 x1,...,xn 以及 m 个约束条件,每个约束条件是由两个其中的变量做差构成的,形如 xixjck,其中 1i,jn,ij,1km 并且 ck 是常数(可以是非负数,也可以是负数)。我们要解决的问题是:求一组解 x1=a1,...,xn=an,使得所有的约束条件得到满足,否则判断出无解。

差分约束系统中的每个约束条件 xixjck 都可以变形成 xixj+ck,这与单源最短路中的三角形不等式 dist[y]dist[x]+z 非常相似。因此,我们可以把每个变量 看做图中的一个结点,对于每个约束条件 xixjck,从结点 j 向结点 i 连一条长度为 ck 的有向边。

注意到,如果 {a1,...,an} 是该差分约束系统的一组解,那么对于任意的常数 d{a1+d,...,an+d} 显然也是该差分约束系统的一组解,因为这样做差后 d 刚好被消掉。

过程

dist[0]=0 并向每一个点连一条权重为 0 边,跑单源最短路,若图中存在负环,则给定的差分约束系统无解,否则,xi=dist[i] 为该差分约束系统的一组解。

时间复杂度 O(nm)

原理

对于一个环,假设两个相邻点编号为 i,j。如果存在负环,那么 wiwja1wiwja2,且 a1+a2<0,也即 a1a2。显然矛盾。

否则,对于 wiwja,在图上体现了 didj+a 的限制。(从 j 连向 i)而 di 体现为 0i 的距离。

扩展

考虑差分约束系统 wiwjck 的求解方式。就是把每个数字取 log 即可。

传递闭包

floyd,但是每条边表示某一种关系 reli,j。对于 reli,jrelj,k,可以维护将其合并到 reli,k

具体地,它是一个布尔矩阵,满足 i 可达 j 的时候为 1 否则为 0。那么用 floyd 就是求可达性的过程,十分自然。

求出来的结果是一个偏序图。

posted @   OIer某罗  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示