差分约束一般是用来求最大值最小值问题的
那么就分为两个问题
求最小值,把所有不等式化为>=然后求最长路
求最大值,把所有不等式化为<=然后求最短路
如果碰到<比如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.
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;
}