差分约束基础

差分约束

满足这种不等式组: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;
}

发布了41 篇原创文章 · 获赞 2 · 访问量 1258

猜你喜欢

转载自blog.csdn.net/qq_41418281/article/details/100114328