标签:
题目: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\n", dis[Max]);
}
int main()
{
int N;
while(~scanf("%d", &N))
{
Min = INF; Max = -INF; cnt = 0;
memset(vis, 0, sizeof(vis));
memset(edge, 0, sizeof(edge));
memset(head, -1, sizeof(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+1, 0); //双向边, 权值不同。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; }
杭电oj1384--Intervals(差分约束)
标签:
原文地址:http://www.cnblogs.com/fengshun/p/4779783.html