POJ 1201 Intervals

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

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

设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;

}

 

 

你可能感兴趣的:(poj)