【SCOI 2011】糖果

【题目】

题目描述:

幼儿园里有 N 个小朋友,Lxhgww 老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,Lxhgww 需要满足小朋友们的 K 个要求。幼儿园的糖果总是有限的,Lxhgww 想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。

输入格式:

输入的第一行是两个整数 N,K。
接下来K行,表示这些点需要满足的关系,每行 3 个数字:X,A,B。
如果 X=1,表示第 A 个小朋友分到的糖果必须和第 B 个小朋友分到的糖果一样多;
如果 X=2,表示第 A 个小朋友分到的糖果必须少于第 B 个小朋友分到的糖果;
如果 X=3,表示第 A 个小朋友分到的糖果必须不少于第 B 个小朋友分到的糖果;
如果 X=4,表示第 A 个小朋友分到的糖果必须多于第 B 个小朋友分到的糖果;
如果 X=5,表示第 A 个小朋友分到的糖果必须不多于第 B 个小朋友分到的糖果;

输出格式:

输出一行,表示 Lxhgww 老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出 -1 。

样例数据:

输入

5 7 
1 1 2 
2 3 2 
4 4 1 
3 4 5 
5 4 5 
2 3 5 
4 5 1

输出

11

备注:

【数据范围】
对于 30% 的数据,保证:N ≤ 100
对于 100% 的数据,保证:N ≤ 100000
对于所有的数据,保证:K ≤ 100000;1 ≤ X ≤ 5;1 ≤ A,B ≤ N

 

【分析】

由于是求最小值,我们要用最长路,并且最后要化成 ≥ 的形式,若用 d_i 表示第 i 个人的糖果,则:

1、x=1 -> d[a]=d[b] -> d[a]-d[b]>=0&&d[b]-d[a]>=0
2、x=2 -> d[a] d[b]-d[a]>0 -> d[b]-d[a]>=1
3、x=3 -> d[a]>=d[b] -> d[a]-d[b]>=0
4、x=4 -> d[a]>d[b] -> d[a]-d[b]>0 -> d[a]-d[b]>=1
5、x=5 -> d[a]<=d[b] -> d[b]-d[a]>=0

按照红色部分连边,然后跑 spfa,若有负环则不能达到要求;否则就可以,累加答案即可

另外,我在代码中写的是 dfs 版的 spfa,判负环应该要快一些,当然队列版的 spfa 应该也可以过

 

【代码】

#include
#include
#include
#define N 1000005
#define M 2000005
using namespace std;
int n,m,t;
int d[N],first[N];
int v[M],w[M],next[M];
bool flag,vis[N];
void add(int x,int y,int z)
{
	t++;
	next[t]=first[x];
	first[x]=t;
	v[t]=y;
	w[t]=z;
}
void SPFA(int x)
{
	int i,j;
	vis[x]=true;
	for(i=first[x];i;i=next[i])
	{
		j=v[i];
		if(d[j]=1;--i)
	{
		d[i]=0;
		vis[i]=false;
		add(0,i,1);
	}
	flag=true;
	SPFA(0);
	if(!flag)  printf("-1");
	else
	{
		for(i=1;i<=n;++i)
		  ans+=d[i];
		printf("%lld",ans);
	}
	return 0;
}

你可能感兴趣的:(#,差分约束)