差分约束
满足这种不等式组:x_i-x_j≤c或 x_i-x_j≥c,小于号大于号可以相互转化
1、x_i-x_j的最大值
如求A-B的最大值,都一致化为小于等于的形式,建图x_i→x_j,以A为起点,B为终点求最短路
2、x_i-x_j的最小值
如求A-B的最小值,都一致化为大于等于的形式,建图x_i→x_j,以A为起点,B为终点求最长路
3、原不等式是否有解
判负环
4、方程给出:X[n-1]-X[0]=T,可以转化为X[n-1]-X[0]<=T&&X[n-1]-X[0]>=T
5、方程给出:X[n-1]-X[0]<T, 可以转化为X[n-1]-X[0]<=T-1
HDU 1384 题意
给出n个区间,每个区间中至少选出c个数,要求满足这n个条件下,至少可以选出多少个数。
思路
假设 ai bi ci 表示在ai到bi这个区间至少选ci个数
构造dis[a]表示从0到a选了dis[a]个数
所以有不等式:
dis[bi]-dis[ai]>=ci
0<=dis[i]-dis[i-1]<=1
最后建图求最大值就可以
代码
#include<bits/stdc++.h>
using namespace std;
#define maxn 50005
#define maxm 200005
#define inf 2e9
#define ll long long
int head[maxn],nextv[maxm],tov[maxm],uvw[maxm],num;
void add(int from,int to,int len)
{
nextv[++num]=head[from];
tov[num]=to;
uvw[num]=len;
head[from]=num;
}
int n,m;
bool visited[maxn]; //标记数组
int dist[maxn]; //源点到顶点i的最短距离
bool SPFA(int source)
{
memset(visited, 0, sizeof(visited));
queue<int> Q;
Q.push(source);
dist[source]=0;
visited[source] = 1;
while (!Q.empty())
{
int u = Q.front();
Q.pop();
visited[u] = 0;
for (int i = head[u]; i ; i=nextv[i])
{
int v=tov[i];
int len=uvw[i];
if (dist[u] + len > dist[v])
{
dist[v] = dist[u] + len;
if (!visited[v])
{
Q.push(v);
visited[v] = 1;
}
}
}
}
return true;
}
void read(int &x)
{
x=0;
bool flag=0;
char ch=getchar();
if(ch=='-') flag=1;
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x*=10,x+=ch-'0',ch=getchar();
if(flag) x=-x;
}
void init()
{
memset(head,0,sizeof(head));
memset(dist,-0x3f,sizeof(dist));
num=0;
}
int main()
{
while(~scanf("%d",&n))
{
init();
int M=0,L=inf;
for(int i=0; i<n; i++)
{
int a,b,c;
read(a),read(b),read(c);
M=max(M,b+1);
L=min(L,a);
add(a,b+1,c);
}
for(int i=L+1; i<=M; i++)
{
add(i-1,i,0);
add(i,i-1,-1);
}
SPFA(L);
printf("%d\n",dist[M]);
}
return 0;
}