差分约束模板

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cbcbcbz/article/details/78328364

差分约束一般是用来求最大值最小值问题的

那么就分为两个问题

求最小值,把所有不等式化为>=然后求最长路


求最大值,把所有不等式化为<=然后求最短路


如果碰到<比如a+b<c 那么就可以转化为a+b<=c-1


然后就是单纯的图论题了


现在来看poj1716

Description

An integer interval [a,b], a < b, is a set of all consecutive integers beginning with a and ending with b. 
Write a program that: finds the minimal number of elements in a set containing at least two different integers from each interval.

Input

The first line of the input contains the number of intervals n, 1 <= n <= 10000. Each of the following n lines contains two integers a, b separated by a single space, 0 <= a < b <= 10000. They are the beginning and the end of an interval.

Output

Output the minimal number of elements in a set containing at least two different integers from each interval.

Sample Input

4
3 6
2 4
0 2
4 7

Sample Output

4

我们这道题是求最小值

可以写出这些不等式

a[en]-a[st-1]>=2

a[k+1]-a[k]<=1

a[k]-a[k+1]<=0

因为是求最小值,那么把不等式化为

a[en]-a[st-1]>=2

a[k]-a[k+1]>=-1

a[k+1]-a[k]>=0


然后放入spfa中求最长路即可

由于st的最小值是0,然后要用到st-1

所以我们这里用en+1,st来代替en,st-1

这里放上不知道能不能ac的代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <string.h>

using namespace std;

const int INF=0x3f3f3f3f;
const int maxm=511111;
const int maxn=111111;

struct EdgeNode
{
    int to;
    int w;
    int next;
};

EdgeNode edges[maxm];
int N,M;
int head[maxn],edge;
bool vis[maxn];
int cou[maxn];

queue <int> que;
int dis[maxn];

void addedge(int u,int v,int c)
{
    edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;
}

void init()
{
    memset(head,-1,sizeof(head));
    edge=0;
}

int spfa(int s,int n)//单源最短路(s为起点,n为节点总数)
{
    int u;
    for (int i=0; i<=n; i++)
        dis[i]=-INF;
    memset(vis,0,sizeof(vis));
    memset(cou,0,sizeof(cou));
    while (!que.empty())
        que.pop();
    que.push(s);
    vis[s]=true;
    dis[s]=0;
    while (!que.empty())
    {
        u=que.front();
        que.pop();
        vis[u]=false;
        for (int i=head[u]; i!=-1; i=edges[i].next)
        {
            int v=edges[i].to;
            int w=edges[i].w;
            if (dis[v]<dis[u]+w)//把这个符号改一下就可以求最短路了
            {
                dis[v]=dis[u]+w;
                if (!vis[v])
                {
                    vis[v]=true;
                    que.push(v);
                    cou[v]++;
                    if (cou[v]>n)//这里是判断负环的操作
                        return 0;
                }
            }
        }
    }
    if (dis[n]==INF)
        return 0;
    else
        return 1;
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        init();

        int Max(0);

        for (int k=1;k<=n;k++)
        {
            int st,en;
            scanf("%d %d",&st,&en);
            addedge(st,en+1,2);
            Max=max(Max,en+1);
        }

        for (int k=0;k<=Max-1;k++)
            {addedge(k,k+1,0);addedge(k+1,k,-1);}

        spfa(0,Max);

        printf("%d\n",dis[Max]);
    }
    return 0;
}



没有更多推荐了,返回首页