您的位置:首页 > 其它

差分约束学习(一)POJ1201

2015-12-03 20:29 323 查看
在vj上找到的差分约束专题:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=50942#overview

一开始好像很快就明白差分约束这是要建立边,然后通过求最短路的方法求解,但真到做的时候发现建立边的过程中真是各种出错,感觉还是要通过做一些题目才能不断总结、理解。

POJ1201:

Intervals

Time Limit: 2000MSMemory Limit: 65536K
Total Submissions: 23755Accepted: 8994
Description

You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn.

Write a program that:

reads the number of intervals, their end points and integers c1, ..., cn from the standard input,

computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i=1,2,...,n,

writes the answer to the standard output.

Input

The first line of the input contains an integer n (1 <= n <= 50000) -- the number of intervals. The following n lines describe the intervals. The (i+1)-th line of the input contains three integers ai, bi and ci separated by single spaces and such that 0 <=
ai <= bi <= 50000 and 1 <= ci <= bi - ai+1.
Output

The output contains exactly one integer equal to the minimal size of set Z sharing at least ci elements with interval [ai, bi], for each i=1,2,...,n.
Sample Input
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1

Sample Output
6


题意是给出了一堆区间[a,b],每个区间和整数集Z都至少有c个相同元素。问整个区间内和整数集Z至少有多少个相同元素。

用val[x]表示[0,x]这个区间和整数集Z相同的元素个数。这样区间[a,b]与整数集Z相同的个数就可以表示为val[b]-val[a-1]。每一个条件就可以化为val[b]-val[a-1]>=c。

然后求的就是val[max]-val[min-1]>=x,x即为所求。

然后就是通过建立边,求图的最短路径。注意差分约束里面难就难在发觉隐含条件建立边,这里面的隐含条件在于1>=val[a+1]-val[a]>=0,所以能够得到两个边val[a+1]-val[a]>=0 与 val[a]-val[a+1]>=-1。

代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#include <queue>
#pragma warning(disable:4996)
using namespace std;

#define INF 1000000007
#define MAXN 50005

struct EDGE
{
	int v;
	int w;
	int next;
}edge[3*MAXN];

int head[MAXN], d[MAXN], vis[MAXN], N, n, Max, Min;

void AddEdge(int u, int v, int w)
{
	edge
.v = v;
	edge
.w = w;
	edge
.next = head[u];
	head[u] = N++;
}

void SPFA()
{
	int x, i, e;
	for (i = Min; i <= Max; i++)
		d[i] = -INF;
	d[Min] = 0;
	
	queue<int>q;
	q.push(Min);
	
	while (!q.empty())
	{
		x = q.front();
		q.pop();
		vis[x] = 0;
		
		for (int e = head[x]; e != -1; e = edge[e].next)
		{
			if (d[edge[e].v] < d[x] + edge[e].w)
			{
				d[edge[e].v] = d[x] + edge[e].w;
				if (!vis[edge[e].v])
				{
					q.push(edge[e].v);
					vis[edge[e].v] = 1;
				}
			}
		}
	}
}

int main()
{
	//freopen("i.txt","r",stdin);
	//freopen("o.txt","w",stdout);
	
	int i;
	int u, v, w;

	while (scanf("%d", &n) != EOF)
	{
		N = 0;
		memset(head, -1, sizeof(head));
		memset(vis, 0, sizeof(vis));
		memset(edge, 0, sizeof(edge));

		Min = INF;
		Max = -INF;

		for (i = 0; i < n; i++)
		{
			scanf("%d%d%d", &u, &v, &w);
			AddEdge(u, v + 1, w);
			Min = min(Min, u);
			Max = max(Max, v + 1);
		}
		for (i = Min; i < Max; i++)
		{
			AddEdge(i, i + 1, 0);
			AddEdge(i + 1, i, -1);
		}
		SPFA();
		printf("%d\n", d[Max]);
	}
	//system("pause");
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: