1. 程式人生 > >【POJ 1201】 Intervals(差分約束系統)

【POJ 1201】 Intervals(差分約束系統)

sub 代碼 idt ear ces oid std one space

【POJ 1201】 Intervals(差分約束系統)


11

1716的升級版 把原本固定的邊權改為不固定。

Intervals
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 23817 Accepted: 9023

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

Source

Southwestern Europe 2002


關於差分約束系統,百度各種大牛博客講的都非常具體,簡單說就是通過不等關系建立約束系統圖。然後跑最短路(大於關系則跑最長路)

回到此題,題目要求找出一個最小集合S。滿足對於n個範圍[ai,bi],S中存在ci個及ci個以上不同的點在範圍內

令Zi表示滿足條件的情況下,0~i點至少有多少點在集合內

則Zbi-Zai >= ci

僅僅有這一個條件構造出來的圖可能不是全然連通的,所以須要找一些“隱含條件”

不難發現 對於相鄰的點 0 <= Zi-Z(i-1) <= 1 保證關系符同樣 轉化為

Zi-Z(i-1) >= 0

Z(i-1)-Zi >= -1

用這三個關系,就可以構造差分約束系統,然後SPFA或者Bellman跑一趟最長路(滿足全部條件)

代碼例如以下:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>

using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 1e5;
const int mod = 1e9+7;
const double eps = 1e-8;

struct Edge
{
	int v,w,next;
};

Edge eg[233333];
int head[50050];
bool vis[50050];
int dis[50050];
int tp,st,en;

void Add(int u,int v,int w)
{
	eg[tp].v = v;
	eg[tp].w = w;
	eg[tp].next = head[u];
	head[u] = tp++;
}

int SPFA()
{
	memset(vis,0,sizeof(vis));
	memset(dis,-INF,sizeof(dis));
	queue <int> q;
	dis[st] = 0;
	vis[st] = 1;
	int u,v,w;

	q.push(st);

	while(!q.empty())
	{
		u = q.front();
		q.pop();
		vis[u] = 0;
		for(int i = head[u]; i != -1; i = eg[i].next)
		{
			v = eg[i].v;
			w = eg[i].w;
			if(dis[v] < dis[u]+w)
			{
				dis[v] = dis[u]+w;
				if(!vis[v]) 
				{
					q.push(v);
					vis[v] = 1;
				}
			}
		}
	}
	return dis[en];
}

int main(int argc,char **argv)
{
	int n;
	int u,v,w;

	while(~scanf("%d",&n))
	{
		tp = 0;
		memset(head,-1,sizeof(head));
		
		en = 0,st = INF;

		while(n--)
		{
			scanf("%d%d%d",&u,&v,&w);
			Add(u,v+1,w);
			en = max(en,v+1);
			st = min(st,u);
		}

		for(int i = st; i < en; ++i)
		{
			Add(i,i+1,0);
			Add(i+1,i,-1);
		}
		printf("%d\n",SPFA());
	}
	return 0;
}


【POJ 1201】 Intervals(差分約束系統)