差分约束模板

来源:互联网 发布:php sqlserver2008 编辑:程序博客网 时间:2024/06/06 08:47

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

那么就分为两个问题

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


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


如果碰到<比如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

43 62 40 24 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;}