UVA11478 [Halum] 二分答案+SPFA差分约束系统

来源:互联网 发布:恒讯营销软件 编辑:程序博客网 时间:2024/06/07 04:42

题目链接


题意:给定一个有向图,每条边都有一个权值。每次你可以选择一个结点v和一个整数d,把所有以v为终点的边的权值减小d,把所有以v为起点的边的权值增加d,最后让所有边的权值的最小值大于零且尽量大。


解题思路:二分答案,找出ans,用差分约束系统来check。

令sum[u],表示u节点在所有的操作后的d之和。

sum[j]-sum[i]<=w[i,j]-ans (i->j)

如果L=1时有负环无解 —————— R=max(w)+1时无负环有无数解


#include <cstdio>#include <iostream>#include <queue>#include <cstring>#include <vector>using namespace std;#define Inf 0x3f3f3f3fconst int N = 505;struct Edge{    int u, v, w;    Edge(int u, int v, int w):u(u),v(v),w(w){}}; struct SPFA{    int n, m;    int d[N], cnt[N];    bool inq[N];    vector<Edge> edges;    vector<int> G[N];    void init(int n){        this->n=n;        for ( int i=1; i<=n; i++ ) G[i].clear();        edges.clear();    }    void addeage(int u, int v, int w){        edges.push_back(Edge(u,v,w));        m=edges.size();        G[u].push_back(m-1);    }    bool spfa(){        for ( int i=1; i<=n; i++ ) inq[i]=0, cnt[i]=0;        queue<int> Q;        for ( int i=1; i<=n; i++ ) { d[i]=0; Q.push(i); }        while( !Q.empty() ){            int u=Q.front(); Q.pop();            inq[u]=false;            for ( int i=0; i<G[u].size(); i++ ){                Edge& e=edges[G[u][i]];                if( d[e.v]>d[u]+e.w ){                    d[e.v]=d[u]+e.w;                    if( !inq[e.v] ){                        inq[e.v]=1;                        if( ++cnt[e.v]==n ) return false;                        Q.push(e.v);                    }                }             }        }        return true;    }}S;int n, m;bool binary(int x){    for ( int i=0; i<m; i++ ) S.edges[i].w-=x;    bool ret=true;    if( !S.spfa() ) ret=false;    for ( int i=0; i<m; i++ ) S.edges[i].w+=x;    return ret;}int main(){    while( ~scanf("%d%d", &n, &m ) ){        S.init(n);        int ub=0;         for ( int i=1; i<=m; i++ ){            int u, v, w;            scanf("%d%d%d", &u, &v, &w );            ub=max(ub,w);            S.addeage(u,v,w);               }        int L=1, R=ub;        if( binary(R) ) {            puts("Infinite");              continue;          }          if( !binary(L) ) {            puts("No Solution");              continue;          }         int ans=L++;        while( L<R ){            int M=(L+R)>>1;            if( !binary(M) ) R=M;            else L=M+1, ans=M;        }        printf("%d\n", ans);    } }
阅读全文
0 0