洛谷 SP116 INTERVAL - Intervals


洛谷 SP116 INTERVAL - Intervals

节选自。如果您想学习差分约束的话不妨看看~

Problem

\(0\sim50000\)选出最少的数,使每个区间至少有\(c\)个数被选。

Solution

这是求最小值,所以将所有的不等式转换成\(\ge\)的形式。

类似于P1250 种树的思想,考虑如何将题目中的

\(sum[x]\)是前缀和:

对于每一个约束条件,可以看成\(sum[b_i]-sum[a_i-1]\ge c_i\).

由于每一个数只能选择一次\(0\le sum_x-sum_{x-1}\le1\).

注意这里下标是从\(0\)开始的,所以就全部\(+1\)就好。

最后,多测不清空,抱玲两行泪。

Code

/**************************************************************
 * Problem: SP116
 * Author: Vanilla_chan
 * Date: 20210330
 * E-Mail: Vanilla_chan@outlook.com
**************************************************************/
//预编译部分已略
#define N 500010
int n,m,s;
int head[N],ver[N<<1],cnt[N],nxt[N<<1],w[N<<1],dis[N],book[N];
int tot;
void insert(int x,int y,int z)
{
	nxt[++tot]=head[x];
	head[x]=tot;
	w[tot]=z;
	ver[tot]=y;
}
struct node
{
	int x,dis;
	node(int xx,int vv)
	{
		x=xx,dis=vv;
	}
};
queueq;
LL ans;
int t;
signed main()
{
// 	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	t=read();
	while(t--)
	{
		tot=0;
		memset(head,0,sizeof(head));
		memset(nxt,0,sizeof(nxt));
		memset(dis,0,sizeof(dis));
		memset(cnt,0,sizeof(cnt));
		memset(w,0,sizeof(w));
		memset(book,0,sizeof(book));
		memset(ver,0,sizeof(ver));
		n=0;
		m=read();
		for(int i=1,a,b,c;i<=m;i++)
		{
			a=read();
			b=read();
			c=read();
			n=max(n,max(a,b));
			insert(a,b+1,c);
		}
		s=n+2;
		for(int i=1;i<=n+1;i++)
		{
			dis[i]=-1;
			insert(s,i,0);
			insert(i-1,i,0);
			insert(i,i-1,-1);
		}
		
		int x;
		q.push(node(s,0));
		while(!q.empty())
		{
			x=q.front().x;
			q.pop();
			book[x]=0;
			for(int i=head[x],v;i;i=nxt[i])
			{
				v=ver[i];
				if(dis[v]n)
						{
							cout<<"-1";
							return 0;
						}
						
						q.push(node(v,dis[v])),book[v]=1,cnt[v]++;
					}
				}
			}
		}
		cout<