ZOJ 2770差分约束

时间:2022-09-21 11:32:57

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1770

题意:参看图论200

分析:差分约束关键还是建图。嗨,图。而且差分约束感觉还有数学的思想。偶数学不好。

ZOJ 2770差分约束ZOJ 2770差分约束View Code
// I'm lanjiangzhou
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f

// aply for the memory of the stack
//#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

const int nmax = 1000+10;
const int emax = 23000+100;
int n;//一共有几个大营
int m;//已知从第i个大营到第j个大营至少有几个士兵,这些信息有m条
int c[nmax];//第i个大营最多有c[i]个士兵
int d[nmax];//d[0]=0;  d[1]=c[1];  d[2]=c[1]+c[2]....即d[i]为前i个大营容量总和
int ei;//边的序号
int dis[nmax];//从源点到个顶点最短路径长度(注意:源点为sn而不是s0)

struct eg{
    int u,v,w;//边:起点,终点,权值
}edges[emax];

void init(){
    ei=0;
    //除源点sn外,其他顶点的最短距离初始为inf
    //则bellman_ford算法的第一重要循环n-1次
    for(int i=0;i<=n;i++) {
        dis[i]=INF;
    }
    dis[0]=0;
    dis[n]=0; //一下bellman_ford算法是以sn为源点的,所以dis[n]=0;
}

bool bellman_ford(){
    //bellman_ford()算法的第一重循环要执行n-1次,n是网络中顶点的个数
    //本题中顶点个数n+1;
    for(int i=0;i<n;i++){
        //假设第k条边的起点是u,终点是v,以下循环考虑第k条边是否会使得源点v0到v的最短距离缩短,
        //即判断dis[edges[k].u]+edges[k].w<dis[edges[k].v]是否成立
        for(int k=0;k<ei;k++){
            int t=dis[edges[k].u]+edges[k].w;
            if(dis[edges[k].u]!=INF&&t<dis[edges[k].v]){
                dis[edges[k].v]=t;
            }
        }
    }
    //以下是检查,若还有更新则说明存在无限循环的负值回路
    for(int k=0;k<ei;k++){
        if(dis[edges[k].u]!=INF&&dis[edges[k].u]+edges[k].w<dis[edges[k].v]){
            return false;
        }
    }
    return true;
}

int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        init();
        int u,v,w;
        //构造不等式组(3)和(4)
        for(int i=1;i<=n;i++){
            scanf("%d",&c[i]);//读入第i个兵营最多有ci个士兵
            edges[ei].u=i-1;
            edges[ei].v=i;
            edges[ei].w=c[i];//构造<i-1,i>,权值为ci;
            ei++;
            edges[ei].u=i;
            edges[ei].v=i-1;
            edges[ei].w=0;  //构造边<i,i-1>,权值为0
            ei++;
            d[i]=c[i]+d[i-1];
        }
        //构造不等式组(1)和(2)
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&u,&v,&w);
            edges[ei].u=v;
            edges[ei].v=u-1;
            edges[ei].w=-w;//构造边<v,u-1>  权值为-w;
            ei++;
        }
        if(!bellman_ford()) printf("Bad Estimations\n");
        else printf("%d\n",dis[n]-dis[0]);
    }
    return 0;
}