POJ 1201 & HDU1384 & ZOJ 1508 Intervals 差分约束

题意:给定n个左右均为闭的区间[a,b],及一个对应的c,意思是从[a,b]中至少要选c个数,现在问要使得所有n个区间均满足上面的条件,至少需要选几个点。

思路:假定t[I]代表是否选取,1为选取,0为不选.设si = t[0]+t[1]+...+t[I]。则s[I-1] - s[I]>=-1,s[I]-s[I-1]>=0.因为s[I]-s[I-1]等于0或1.s[b]-s[a-1]>=c.由这三个条件建图

差分约束:https://wenku.baidu.com/view/b061cb986bec0975f465e234.html

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 50010;
const int INF = 1<<30;
int n,num,left;
struct edge
{
	int from,to,w;
};
vector<edge> edges;
vector<int> g[maxn];
int inq[maxn],d[maxn],cnt[maxn];
void addedge(int from,int to,int w)
{
	edges.push_back(edge{from,to,w});
	int m = edges.size();
	g[from].push_back(m-1);
}
bool bellman_ford(int s)
{
	queue<int> q;
	q.push(s);
	memset(cnt,0,sizeof(cnt));
	memset(inq,0,sizeof(inq));
	for(int i=0;i<=num;i++)
	d[i]=INF;
	d[s]=0;
	inq[s]=1;
	while(!q.empty())
	{
		int u = q.front();q.pop();
		inq[u]=0;
		for(int i=0;i<g[u].size();i++)
		{
			edge &e=edges[g[u][i]];
			if(d[e.to]>d[u]+e.w)
			{
				d[e.to]=d[u]+e.w;
				if(!inq[e.to])
				{
					q.push(e.to);inq[e.to]=1;
					if(++cnt[e.to]>n)return false;
				}
			}
		}
	}
	return true;
}
int main()
{
	while(scanf("%d",&n)!=EOF)
	{
		for(int i=left-1;i<=num;i++)
		g[i].clear();
		edges.clear();
		num=-(1<<30);
		left=1<<30;
		for(int i=0;i<n;i++)
		{
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			addedge(b,a-1,-c);
			if(b>num)num=b;
			if(a<left)left=a;
		}
		for(int i=left;i<=num;i++)
		{
			addedge(i,i-1,0);
			addedge(i-1,i,1);
		}
			bellman_ford(num);		
		printf("%d\n",-d[left-1]);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值