[差分约束/SPFA] 集合 HDU图论01

Intervals

Time Limit : 10000/5000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 113   Accepted Submission(s) : 43

Font: Times New Roman | Verdana | Georgia

Font Size:  

Problem 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 endpoints 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 <= 50 000) - 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 <= 50 000 and 1 <= ci <= bi - ai + 1.

Process to the end of file.

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

Author

1384

//根据x轴上各点关系建图 -> 差分约束系统

#include <bits/stdc++.h>
using namespace std;

const int maxn = 50005;
const int inf = 1e9;

int d[maxn];
int u[3*maxn], v[3*maxn], w[3*maxn], nx[3*maxn], fr[3*maxn];
//一点连接多条边

int T;
void add ( int a, int b, int s ) //邻接表建图
{
	u[T] = a;
	v[T] = b;
	w[T] = s;
	nx[T] = fr[a];
	fr[a] = T;
	T++;
}  //建边时>= -> 求最长路

void spfa ( int Min, int Max ) //带负权边
{
	bool vis[maxn];  //是否在队列中
	for ( int i = Min; i <= Max; i++ )
	{
		d[i] = -inf;
		vis[i] = 0; //初始化为极小值
	}
	d[Min] = 0;
	queue<int>q;
	q.push ( Min );
	vis[Min] = 1;
	while ( !q.empty() )
	{
		int &t = q.front();
		q.pop();
		vis[t] = 0;
		for ( int i = fr[t]; i != -1; i = nx[i] )
			if ( d[v[i]] < d[t] + w[i] )
			{
				//更新最长路
				d[v[i]] = d[t] + w[i];
				if ( !vis[v[i]] )
				{
					q.push ( v[i] );
					vis[v[i]] = 1;
				}
			}
	}
}

int main()
{
	int m;
	while ( ~scanf ( "%d", &m ) )
	{
		T = 0;
		memset ( fr, -1, sizeof ( fr ) );
		int Min = inf, Max = -inf;
		while ( m-- )
		{
			int a, b, s;
			scanf ( "%d%d%d", &a, &b, &s );
			add ( a - 1, b, s );
			Min = min ( Min, a - 1 );
			Max = max ( Max, b );
		}
		for ( int i = Min; i <= Max; i++ )
			add ( i, i + 1, 0 );
		//相邻两点从左向右
		for ( int i = Min; i <= Max; i++ )
			add ( i + 1, i, -1 );
		//相邻两点从右到左
		spfa ( Min, Max );
		printf ( "%d\n", d[Max] );
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/ummmmm/article/details/80194019