• UVA11478 Halum(差分约束系统)


    刘汝佳新书--训练指南

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

    分析:因为不同的操作互不影响,因此可以按任意顺序实施这些操作。另外,对于同一个点的多次操作可以合并,因此可以令sum(u)为作用于结点u之上的所有d之和。这样,本题的目标就是确定所有的sum(u),使得操作之后所有边权的最小值尽量大。

    “最小值最大”使用二分答案的方法。二分答案x之后,问题转化为是否可以让操作完毕后每条边的权值均不小于x。对于边a->b,不难发现操作完毕后它的权值为w(a,b)+sum(a)-sum(b),因此每条边a->b都可以列出一个不等式w(a,b)+sum(a)-sum(b)>=x,移项得sum(b)-sum(a)<=w(a,b)-x。这样,我们实际得到一个差分约束系统

    查分约束系统是指一个不等式组,每个不等式形如xj-xi<=bk,这里的bk是一些事先已知的常数。这个不等式类似于最短路中的不等式d[v]<=d[u]+w(u,v),我们可以用最短路算法求解:对于约束条件xj-xi《=bk,新建一条边i-->j,权值为bk如果图中有负权环,则差分约束系统无解。

    // File Name: 11478.cpp
    // Author: zlbing
    // Created Time: 2013/2/15 13:16:21
    
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    #include<cstdio>
    #include<set>
    #include<map>
    #include<vector>
    #include<cstring>
    #include<stack>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define MAXN 505
    #define INF 10050
    struct Edge{
        int from,to;
        int dist;
    };
    struct BellmanFord{
        int n,m;
        vector<Edge>edges;
        vector<int>G[MAXN];
        bool inq[MAXN];
        int d[MAXN];
        int p[MAXN];
        int cnt[MAXN];
        void init(int n)
        {
            this->n=n;
            for(int i=0;i<n;i++)G[i].clear();
        }
        void AddEdge(int from,int to,int dist)
        {
            edges.push_back((Edge){from,to,dist});
            m=edges.size();
            G[from].push_back(m-1);
        }
        bool negativeCycle()
        {
            queue<int>Q;
            memset(inq,0,sizeof(inq));
            memset(cnt,0,sizeof(cnt));
            for(int i=0;i<n;i++)
            {
            d[i]=0;inq[0]=true;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.to]>d[u]+e.dist)
                    {
                        d[e.to]=d[u]+e.dist;
                        p[e.to]=G[u][i];
                        if(!inq[e.to])
                        {
                            Q.push(e.to);
                            inq[e.to]=true;
                            if(++cnt[e.to]>n)
                                return true;
                        }
                    }
                }
            }
            return false;
        }
    };
    BellmanFord solver;
    bool test(int x)
    {
        for(int i=0;i<solver.m;i++)
            solver.edges[i].dist-=x;
        bool ret=solver.negativeCycle();
        for(int i=0;i<solver.m;i++)
            solver.edges[i].dist+=x;
        return ret;
    }
    int main(){
        int n,m;
        while(~scanf("%d%d",&n,&m))
        {
            int a,b,c;
            solver.init(n);
            for(int i=0;i<m;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                a--,b--;
                solver.AddEdge(a,b,c);
            }
            if(!test(INF))printf("Infinite\n");
            else if(test(1))printf("No Solution\n");
            else{
                int L=1,R=INF;
                while(L<R)
                {
                    int mid=L+(R-L+1)/2;
                    if(test(mid))R=mid-1;
                    else L=mid;
                }
                 printf("%d\n",L);
            }
        }
        return 0;
    }
  • 相关阅读:
    0916 编程实验一 词法分析程序 总结
    0916 编程实验一 词法分析程序
    0909编译
    C语言文法
    词法分析编译感想
    词法分析
    0909 编译原理
    0429团队3.0
    0428 团队项目合作2.0作业
    0422 数学口袋精灵app
  • 原文地址:https://www.cnblogs.com/arbitrary/p/2912792.html
Copyright © 2020-2023  润新知