杭电oj1384--Intervals(差分约束)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1384

题意:  N 表示有几组测试数据, a , b, c -- >[a, b] 表示一个闭区间, c 表示闭区间内符合条件的点数。 求满组符合N个条件所需最少的点。

这种题主要是找约束方程。

约束方程有两个:(不得不吐个槽, 真nm不好想),设 s[i] 为0 ~ i在集合Z中满足点的个数, 集合Z为最终所求集合;

 1、在集合[a, b]中, s[a+1] - s[b] >= c . (注意集合长度、 这里要用最长路解决问题----->注意建边方向)。

 2、1 >= s[i+1] - s[i] >= 0; (这条件不太明显,Nm-.-). 转化一下---> s[i] >= s[i-1] - 1 && s[i + 1] >= 0 + s[i]方向!!!) yuan point = imPoRtant.

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#define min(a, b) a<b? a:b
#define max(a, b) a>b? a:b
using namespace std;
const int INF = 0x3f3f3f3f;
int dis[50010], vis[50010], Min, Max;
struct Edge
{
    int from, to, val, next;
} edge[50005*3];
int head[50005], cnt;
void Add(int a, int b, int c)
{
    Edge E = {a, b, c, head[a]};
    edge[cnt] = E; 
    head[a] = cnt++;
}
void Spfa()
{
    for(int i = Min; i <= Max; i++)
        dis[i] = -INF;
    dis[Min] = 0;            //最长路;
    queue<int> Q;
    Q.push(Min);
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop();
        vis[u] = 0;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if(dis[v] < dis[u] + edge[i].val)
            {
                dis[v] = dis[u] + edge[i].val;
                if(!vis[v])
                {
                    vis[v] = 1;
                    Q.push(v);
                }
            }    
        }    
    } 
    printf("%d ", dis[Max]);
}
int main()
{
    int N;
    while(~scanf("%d", &N))
    {
        Min = INF; Max = -INF;  cnt = 0;
        memset(vis, 0sizeof(vis));
        memset(edge, 0sizeof(edge));
        memset(head, -1sizeof(head));
        for(int i = 0; i < N; i++)
        {
            int u, v, w;
            scanf("%d %d %d", &u, &v, &w);
            Add(u, v+1, w);                  //s[a+1] - s[b] >= c ;
            Min = min(Min, u);               //找大致区间;
            Max = max(Max, v+1); 
        }
        for(int i = Min; i < Max; i++)
        {
            Add(i, i+10);                 //双向边, 权值不同。1 >= s[i+1] - s[i] >= 0---> s[i] >= s[i-1] - 1 && s[i + 1] >= 0 + s[i]
            Add(i+1, i, -1);    
        } 
        Spfa();
    }
    return 0; }


原文地址:https://www.cnblogs.com/soTired/p/4779783.html