Poj 1201 Intervals

题目链接:http://poj.org/problem?id=1201

差分约束系统。

我们用s[i]代表从[0,i]所含有的元素和

在本题中,如果[a,b]中有c个元素,那么:

s[b]-s[a-1]>=c,我们可以推得:s[a-1] - s[b] <= -c

同时,由于每一个值上最多只能含有一个元素,那么:

s[i] - s[i-1]<=1 

s[i] - s[i-1]>=0 推得:s[i-1] - s[i] <=0

这样:我们有了三个约束不等式:

s[a-1] - s[b] <= -c

s[i] - s[i-1]<=1 

s[i-1] - s[i] <=0

于是:

假设题目中所有查询的所在区间范围是:[start,end]的话,那么:

我们只要求出:s[end] -s[start-1] >= M就可以了。

其中M就是我们要的最小值。

我们可以整理成我们容易求解的形式:即:s[start-1] - start[end] <= -M

就是求从end这一点,到start-1这一点的最短路径。

然后求出的最短路径求相反数就是M了。

注意题目要求a可以为0,所有都++避免下标为负。Bellmanford会超时,spfa是首选。

 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <math.h>

#include <stack>

#include <queue>

#include <algorithm>

#include <iostream>



using namespace std;



#define Maxn 50005

#define Maxm 200005

#define INF 0x3f3f3f3f



int first[Maxn];

int next[Maxm];

int total;

struct Edge

{

    int a,b;

    int w;

}edge[Maxm];



int dist[Maxn];

int vis[Maxn];

void init()

{

    total = 0;

    memset(first,-1,sizeof(first));

}

void addEdge(int a,int b,int w)

{

    edge[total].a = a,edge[total].b = b,edge[total].w = w;

    next[total] = first[a];

    first[a] = total++;

}

/*

bool bellmanFord(int start,int pointNum,int m)

{

    memset(dist,0x3f,sizeof(dist));

    dist[start] = 0;

    for(int i=0;i<pointNum-1;i++)

    {

        for(int j=0;j<m;j++)

        {

            int a = edge[j].a;

            int b = edge[j].b;

            int w = edge[j].w;

            if(dist[a] + w < dist[b]) dist[b] = dist[a] + w;

        }

    }

    for(int i=0;i<m;i++)

    {

        int a = edge[i].a;

        int b = edge[i].b;

        int w = edge[i].w;

        if(dist[a] + w < dist[b]) 

        {

            return false;

        }

    }

    return true;

}*/

int cnt[Maxn];

bool spfa(int s,int n)

{

    memset(dist,0x3f,sizeof(dist));

    memset(vis,0,sizeof(vis));

    memset(cnt,0,sizeof(cnt));

    dist[s] = 0;

    queue<int> q;

    q.push(s);

    vis[s] = 1;

    while(!q.empty())

    {

        int temp = q.front();

        q.pop();

        vis[temp] = 0;

        for(int i=first[temp];i!=-1;i=next[i])

        {

            int a = edge[i].a;

            int b = edge[i].b;

            int w = edge[i].w;

            if(dist[a] + w < dist[b])

            {

                dist[b] = dist[a] + w;

                if(!vis[b])

                {

                    vis[b] = 1;

                    cnt[b]++;

                    if(cnt[b] > n) return false;

                    q.push(b);

                }

            }

        }

    }

    //判负环

    return true;

}

int main()

{

    #ifndef ONLINE_JUDGE

        freopen("in.txt","r",stdin);

    #endif

    int n;

    int a,b,c;

    int start,end;

    while(scanf(" %d",&n)!=EOF)

    {

        init();

        start = INF,end = -INF;

        for(int i=1;i<=n;i++)

        {

            scanf(" %d %d %d",&a,&b,&c);

            a++,b++;

            start = min(start,a);

            end = max(end,b);

            //b-a>=c -> a-b<=-c

            addEdge(b,a-1,-c);

        }

        for(int i=start;i<=end;i++)

        {

            //Si - Si-1 <= 1

            addEdge(i-1,i,1);

            //Si-1 - Si <= 0

            addEdge(i,i-1,0);

        }

        //if(!bellmanFord(end,end-start+2,total)) continue;

        if(!spfa(end,end-start+2)) continue;

        int ans = -dist[start-1];

        printf("%d\n",ans);

    }

    return 0;

}


 

 

你可能感兴趣的:(poj)