线性约束

将所有不等式化成 \(d[a] - d[b] <= c\) 的形式,即有 \(a,b,c\)这条有向边,跑最短路即可


#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
typedef  pair<int,int> pii;

const int N = 1e5+10;
const int inf = 0x3f3f3f3f;
struct E{
    int u,v,nxt,w;
    E(){}
    E(int u,int v,int nxt,int w):u(u),v(v),nxt(nxt),w(w){}
}eg[N*3];
int head[N],cnt[N],vis[N],tot;
ll d[N];
void init(){
    tot = 0 ; memset(head,-1,sizeof head);
}
void add(int u,int v,int w){
    eg[++tot].u = u;    eg[tot].v = v;  eg[tot].w = w;  eg[tot].nxt = head[u]; head[u] = tot;
}
int n,ml,md;
bool spfa(int s){
    fill(d,d+n+1,inf);
    memset(vis,0,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    queue<int> q;
    q.push(s); d[s] = 0; vis[s] = 1;
    while(q.size()){
        int u = q.front();  q.pop();
        vis[u] = 0;
        for(int i=head[u];~i;i=eg[i].nxt){
            int v = eg[i].v , w = eg[i].w;
            if(d[v] > d[u] + w){
                d[v] = d[u] + w;
                cnt[v] = cnt[u] + 1;
                if(cnt[v]>n){
                    return true;
                }
                if(!vis[v]){
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    return false;
}
int main(){
    int u,v,w;
    init();
    scanf("%d%d%d",&n,&ml,&md);
    for(int i=1;i<=ml;++i){
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        // add(v,u,w);
    }
    for(int i=1;i<=md;++i){
        scanf("%d%d%d",&u,&v,&w);
        add(v,u,-w);    // 移项变号
    }
    for(int i=1;i<n;++i){
        add(i+1,i,0);   // 如果能重合就是0,不能重合就是-1
    }
    if(spfa(1))    puts("-1");
    else if(d[n]==inf)  puts("-2");
    else printf("%lld\n",d[n]);
    return 0;
}

大佬博客先马住

01-15 08:58