• UVA


    题目链接:

    http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34651

    题意:

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

    题解:

    最小值最大,可以用二分,这样可以得到一个差分约束系统,然后每次都用最短路跑。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 555;
    const int maxm = 2777;
    
    struct Edge {
        int v, w;
        Edge(int v, int w) :v(v), w(w) {}
        Edge() {}
    };
    
    vector<Edge> egs;
    vector<int> G[maxn];
    int tot = 0;
    int n, m;
    
    void addEdge(int u, int v, int w) {
        egs.push_back(Edge(v, w));
        tot = egs.size();
        G[u].push_back(tot - 1);
    }
    
    bool inq[maxn];
    int d[maxn];
    int cnt[maxn];
    bool spfa(int x) {
        bool ret = true;
    
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < G[i].size(); j++) {
                Edge& e = egs[G[i][j]];
                e.w -= x;
            }
        }
        memset(inq, 0, sizeof(inq));
        memset(cnt, 0, sizeof(cnt));
        memset(d, 0x3f, sizeof(d));
    
        queue<int> Q;
        d[0] = 0; inq[0] = true; Q.push(0);
        while (!Q.empty()) {
            int u = Q.front(); Q.pop();
            inq[u] = false;
            for (int i = 0; i < G[u].size(); i++) {
                Edge& e = egs[G[u][i]];
                if (d[e.v] > d[u] + e.w) {
                    d[e.v] = d[u] + e.w;
                    if (!inq[e.v]) {
                        Q.push(e.v); inq[e.v] = true;
                        if (++cnt[e.v] > n) {
                            ret = false; break;
                        }
                    }
                }
            }
            if (ret == false) break;
            //printf("u:%d
    x:%d
    ", u,x);
            //printf("in circle
    ");
        }
    
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < G[i].size(); j++) {
                Edge& e = egs[G[i][j]];
                e.w += x;
            }
        }
    
        return ret;
    }
    
    void init() {
        for (int i = 0; i < n; i++) G[i].clear();
        egs.clear();
    }
    
    int main() {
        while (scanf("%d%d", &n, &m) == 2 && n) {
            n++;
            init();
            int l = 1, r = -1;
            for (int i = 0; i < m; i++) {
                int u, v, w;
                scanf("%d%d%d", &u, &v, &w);
                r = max(r, w);
                addEdge(u, v, w);
            }
            for (int i = 1; i < n; i++) {
                addEdge(0, i, 0);
            }
            r++;
            if (!spfa(1)) {
                printf("No Solution
    ");
            }
            else if (spfa(r)) {
                printf("Infinite
    ");
            }
            else {
                while (l + 1 < r) {
                    int mid = l + (r - l) / 2;
                    if (spfa(mid)) l = mid;
                    else r = mid;
                    //printf("here!
    ");
                }
                printf("%d
    ", l);
            }
    
        }
        return 0;
    }
    
    /*
    1
    2 10
    1
    2 -10
    3
    2 4
    3 2
    1 5
    5
    3 4
    2 5
    4 2
    1 0
    2 -1
    */
  • 相关阅读:
    DLL导出类避免地狱问题的完美解决方案
    WorldWind源码剖析系列:影像图层类ImageLayer
    WorldWind源码剖析系列:插件类Plugin、插件信息类PluginInfo和插件编译器类PluginCompiler
    多线程中的锁系统(一)-基础用法
    [转]分布式计算框架综述
    C#自定义控件开发
    GDI+编程小结
    C#自定义控件
    WorldWind源码剖析系列:窗口定制控件类WorldWindow
    WorldWind源码剖析系列:四叉树瓦片集合类QuadTileSet
  • 原文地址:https://www.cnblogs.com/fenice/p/5532549.html
Copyright © 2020-2023  润新知