zoj 1508


差分约束系统。


对于约束条件 [aibi] 内至少有 ci 个数。

sum(bi)sum(ai1)ci

sum(ai1)sum(bi)ci

而最短路满足 distjdisti+wi,j

disti=sum(i) ,边 (bi ,  ai1 , ci)


还有两个条件,

sum(i1)sum(i)

sum(i)sum(i1)+1

建图跑最短路即可。


另外注意数据范围, ai,bi 的值可以为 0 <script type="math/tex" id="MathJax-Element-1661">0</script>。


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <utility>
#include <iostream>
#include <algorithm>

template<class Num>void read(Num &x)
{
    char c; int flag = 1;
    while((c = getchar()) < '0' || c > '9')
        if(c == '-') flag *= -1;
    x = c - '0';
    while((c = getchar()) >= '0' && c <= '9')
        x = (x<<3) + (x<<1) + (c-'0');
    x *= flag;
    return;
}
template<class Num>void write(Num x)
{
    if(x < 0) putchar('-'), x = -x;
    static char s[20];int sl = 0;
    while(x) s[sl++] = x%10 + '0',x /= 10;
    if(!sl) {putchar('0');return;}
    while(sl) putchar(s[--sl]);
}

const int maxn = 50050, maxm = maxn*3, size = 50001, INF = 0x3f3f3f3f;
//s[bi] - s[ai - 1] >= ci
//0 <= s[i] - s[i - 1] <= 1

//dist[i] <= dist[j] + w[j][i]
//s[ai - 1] <= s[bi] - ci   w[bi][ai - 1] = - ci
//s[i - 1] <= s[i]          w[i][i - 1] = 0
//s[i] <= s[i - 1] + 1      w[i - 1][i] = 1 
//dist[size] = 0, ans = -dist[0]

#define REP(__i,__st,__ed) for(int __i = (__st); __i <= (__ed); __i++)

struct Edge
{
    int v, w, next;

    Edge(int v = 0,int w = 0,int next = 0):v(v),w(w),next(next){}

}edge[maxm];

int head[maxn], el;
int _head[maxn], _el;

int n;

void newedge(int u,int v, int w)
{
    edge[++el] = Edge(v, w, head[u]), head[u] = el;
}

int SPFA(int S,int T)
{
    static int line[maxn], dist[maxn];
    static bool hash[maxn];
    int f = 0, r = 0;

    REP(i, 0, size) dist[i] = INF;

    dist[S] = 0, line[r] = S;
    r = (r + 1)%maxn, hash[S] = true;

    while(f != r)
    {
        int x = line[f], p;
        line[f] = 0, f = (f + 1)%maxn;
        hash[x] = false;

        for(int i = head[x]; i ; i = edge[i].next)
        {
            int tmp = dist[x] + edge[i].w;

            if(tmp < dist[p = edge[i].v])
            {
                dist[p] = tmp;

                if(!hash[p])
                {
                    if(dist[p] <= dist[line[f]])
                        f = (f - 1 + maxn)%maxn, line[f] = p;
                    else
                        line[r] = p, r = (r + 1)%maxn;

                    hash[p] = true;      
                }
            }
        }
    }

    return -dist[T];
}
int main()
{   
#ifndef ONLINE_JUDGE
    freopen("1508.in","r",stdin);
    freopen("1508.out","w",stdout);
#endif

    REP(i, 1, size)
    {
        newedge(i - 1, i, 1);
        newedge(i, i - 1, 0);
    }
    _el = el;
    REP(i, 0, size) _head[i] = head[i];

    while(scanf("%d", &n) != EOF)
    {
        int a, b, c;

        el = _el;
        REP(i, 0, size) head[i] = _head[i];

        REP(i, 1, n)
        {
            read(a), read(b), read(c);
            newedge(b + 1, a, -c);
        }

        write(SPFA(size, 0)), puts("");
    }

#ifndef ONLINE_JUDGE    
    fclose(stdin);
    fclose(stdout);
#endif  
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值