IT民工
加油!

做的第一个差分约束的题。读完题后一脸茫然,不会建图。看了算法导论,其实这是

一个建立<= 差分约束系统的过程。

设s[x] = 从0 到x 的所有在集合中的数的个数,则ai到bi的个数即S[bi] - S[ai-1]。
因此有:

(1) S[bi] - S[ai-1] >= ci。 

又根据s[x]本身的性质,后面的一定不比前面的小,后面的最多比前面多一,有:
(2)  s[i + 1] - s[i] >= 0
(3)  s[i + 1] - s[i] <= 1
根据这三个约束条件建图,使图中每一组边,均满足:

S[ai - 1] <= S[bi] - ci    
S[i] <= S[i - 1] + 1
S[i - 1] <= S[i] 

建完图,用Bellman-Ford来迭代就OK了。

/*Accepted    2076K    360MS    C++    1203B    2012-08-06 12:58:49*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
using namespace std;

const int MAXN = 50050, inf = 0x3f3f3f3f;
int u[MAXN * 3], v[MAXN * 3], w[MAXN * 3];
int a, b, c, e, dist[MAXN];

int n, right;

void addedge(int a, int b, int c)
{
    u[e] = a, v[e] = b, w[e] = c;
    e ++;
}

void ReadGraph()
{
    int i;
    e = 0, right = 0;
    memset(dist, 0, sizeof dist);
    for(i = 0; i < n; i ++)
    {
        scanf("%d%d%d", &a, &b, &c);
        if(b > right)
            right = b;
        addedge(b, a - 1, -c);
    }
    for(i = 0; i < right; i ++)
    {
        addedge(i, i + 1, 1);
        addedge(i + 1, i, 0);
    }
}

int BellmanFord(int S, int T)
{
    int i;
    bool flag;
    while(flag)
    {
        flag = false;
        for(i = 0; i < e; i ++)
        {
            if(dist[v[i]] > dist[u[i]] + w[i])
            {
                flag = true;
                dist[v[i]] = dist[u[i]] + w[i];
            }
        }
    }
    return dist[S] - dist[T];
}

int main()
{
    while(scanf("%d", &n) == 1)
    {
        ReadGraph();
        printf("%d\n", BellmanFord(right, 0));
    }
    return 0;
}

下面是SPFA的代码:

/*Accepted    2776K    422MS    C++    1687B    2012-08-06 11:19:26*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
using namespace std;

const int MAXN = 50050, inf = 0x3f3f3f3f;
int first[MAXN], next[MAXN * 3], v[MAXN * 3], w[MAXN * 3];
int a, b, c, e, dist[MAXN], inq[MAXN];

int n, right;

void addedge(int a, int b, int c)
{
    v[e] = b, w[e] = c;
    next[e] = first[a], first[a] = e ++;
}

void ReadGraph()
{
    int i;
    e = 0, right = 0;
    memset(first, -1, sizeof first);
    for(i = 0; i < n; i ++)
    {
        scanf("%d%d%d", &a, &b, &c);
        ++ a, ++ b;
        if(b > right)
            right = b;
        addedge(b, a - 1, -c);
    }
    for(i = 1; i <= right; i ++)
    {
        dist[i] = inf;
        addedge(i - 1, i, 1);
        addedge(i, i - 1, 0);
    }
}

int SPFA(int S, int T)
{
    queue<int> q;
    memset(inq, 0, sizeof (int) * (right + 1));
    dist[0] = inf;
    dist[S] = 0;
    q.push(S);
    inq[S] = 1;
    while(!q.empty())
    {
        int x = q.front();
        q.pop();
        inq[x] = 0;
        for(int i = first[x]; i != -1; i = next[i])
        {
            if(dist[v[i]] > dist[x] + w[i])
            {
                dist[v[i]] = dist[x] + w[i];
                if(!inq[v[i]])
                {
                    inq[v[i]] = 1;
                    q.push(v[i]);
                }
            }
        }
    }
    return dist[T];
}

int main()
{
    while(scanf("%d", &n) == 1)
    {
        ReadGraph();
        printf("%d\n", -SPFA(right, 0));
    }
    return 0;
}

 

 

posted on 2012-08-06 13:08  找回失去的  阅读(284)  评论(0编辑  收藏  举报