ZOJ2770

47 篇文章 0 订阅

差分约束,我们定义x[i]为第i个营的人数,定义dist[i]=x[0]+x[1]+...x[i],其中x[0]=0,则可知我们要求的为dist[n]。 
    对于差分不等式,a - b <= c ,建一条 b 到 a 的权值为 c 的边,求的是最短路,得到的是最大值;对于不等式 a - b >= c ,建一条 b 到 a 的权值为 c 的边,求的是最长路,得到的是最小值。这题由于求最小值,所以我们用的是第二种。 
    对于题目,我们可以有如下约束 
    Ci有: x[i]=dist[i]-dist[i-1],则有dist[i]-dist[i-1]>=0,且dist[i-1]-dist[i]>=-Ci 
    i,j,k有: s[j]-s[i-1]>=k 
    还有: dist[i]>=0,即dist[i]-dist[0]>=0 
    因为是求最小值,同时图的建立是按照小于等于进行,所以我们就要从负无穷约束到最小值,用SPFA求最长路即可。 
    SPFA过程中判断是否有环。
-dis[i



#include <iostream>

#include <stdio.h>
#include <string.h>


using namespace std;


#define Edge_count 30000
#define Pnt_count 2000
#define INF 0x1f1f1f1f


struct edge
{
    int adj;
    int point;
    int w;
    edge(int a, int p, int ww):adj(a),point(p),w(ww){}
    edge():adj(0),point(0),w(0){}
};
edge e[Edge_count];
int dis[Pnt_count];


int c[2000];


bool bellman(int src,int edge_count,int pnt_count)
{
    memset(dis,0x1f,sizeof(dis));
    dis[src] = 0;


    for(int i = 1; i<pnt_count; i++)
    {
        for( int j = 1; j <= edge_count; j++)
        {
             if(dis[e[j].adj] < INF && dis[e[j].adj] + e[j].w < dis[e[j].point])
                dis[e[j].point] = dis[e[j].adj] + e[j].w;
        }
    }


    for( int j = 1; j <= edge_count; j++)
        {
             if(dis[e[j].adj] < INF && dis[e[j].adj] + e[j].w < dis[e[j].point])
               return 0;
        }
    return 1;
}


int main()
{
    int n,m;
    while(~scanf("%d %d",&n, &m))
    {
        for( int i = 1; i<=n; i++)
          scanf("%d",&c[i]);


        for( int i = 1; i<=m; i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u, &v, &w);
            e[i] = edge(v,u-1,-w);
        }


        for( int i = 1; i<=n; i++)
        {
            e[m+i] = edge(i-1,i,c[i]);
            e[m+n+i] = edge(i,i-1,0);
        }


        if(bellman(n,m+n+n,n+1))
         cout<<-dis[0]<<endl;
        else
         cout<<"Bad Estimations"<<endl;
    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值