Description
幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的
Input
输入的第一行是两个整数N,
接下来K行,表示这些点需要满足的关系,每行3个数字,
如果X=1, 表示第A个小朋友分到的糖果必须和第
如果X=2, 表示第A个小朋友分到的糖果必须少于第
如果X=3, 表示第A个小朋友分到的糖果必须不少于第
如果X=4, 表示第A个小朋友分到的糖果必须多于第
如果X=5, 表示第A个小朋友分到的糖果必须不多于第
Output
输出一行,表示lxhgww老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。
Sample Input
5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1
Sample Output
11
HINT
数据范围
对于30%的数据,保证 N<=100。
对于100%的数据,保证 N<=100000。
对于所有的数据,保证 K<=100000,1<=X<=5,1<=A,B<=N。
Source
Day1
思路
差分约束的入门题。那我来介绍一遍差分约束吧。
差分约束
要解决的问题:有一些值a1..an和一些限制条件,每个限制条件(x,y,w)的意义是:限制ax<=ay+w,求a1..an这些数的值。
思想:把这些值放到图上,由于一个图distv<=distu+valedge(u,v)(v是u的儿子节点),那么令a为图上的
回到这一题
这道题可以建立一个源点S,令
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
const int maxn=100000;
int pre[(maxn<<2)+10],now[maxn+10],son[(maxn<<2)+10],tot,val[(maxn<<2)+10];
int n,k,dist[maxn+10],b[maxn+10],head,tail,q[(maxn<<4)+10],sum[maxn+10];
long long ans;
int ins(int a,int b,int c)
{
tot++;
pre[tot]=now[a];
now[a]=tot;
son[tot]=b;
val[tot]=c;
return 0;
}
int spfa(int s)
{
head=0;
tail=1;
q[1]=s;
b[s]=1;
dist[s]=0;
while(head!=tail)
{
head++;
if(head>=n<<3)
{
head=0;
}
int u=q[head],j=now[u];
while(j)
{
int v=son[j];
if(dist[v]<dist[u]+val[j])
{
sum[v]++;
if(sum[v]>=n)
{
return 1;
}
dist[v]=dist[u]+val[j];
if(!b[v])
{
tail++;
if(tail>=n<<3)
{
tail=0;
}
q[tail]=v;
b[v]=1;
}
}
j=pre[j];
}
b[u]=0;
}
return 0;
}
int main()
{
scanf("%d%d",&n,&k);
while(k--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
switch(a)
{
case 1:
{
ins(b,c,0);
ins(c,b,0);
break;
}
case 2:
{
if(b==c)
{
puts("-1");
return 0;
}
ins(b,c,1);
break;
}
case 3:
{
ins(c,b,0);
break;
}
case 4:
{
if(b==c)
{
puts("-1");
return 0;
}
ins(c,b,1);
break;
}
case 5:
{
ins(b,c,0);
break;
}
}
}
for(int i=n; i>0; i--)
{
ins(0,i,1);
}
if(spfa(0))
{
puts("-1");
return 0;
}
for(int i=1; i<=n; i++)
{
ans+=dist[i];
}
printf("%lld\n",ans);
return 0;
}