题目描述
幼儿园里有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。
题解
裸的差分约束系统啊!!
只有一点需要注意 就是每个人都要发糖 也就是说每个人都至少发一块糖 所以源点给每个点连边的时候连权值为1的边 不是权值为0的边
最后说个题外话 这个题原数据有一个点是一个十万的链 有个玄学方法可以解决 就是源点连边的时候倒着加边(从n加到1)
另外有一个点存在a=b的情况 x=2和x=4的情况下如果a=b直接输出-1
代码
type
arr=record
x,y,w,next:longint;
end;
var
ans:int64;
n,k,nm:longint;
a:array [0..800001] of arr;
st,ls,len:array [0..400001] of longint;
d:array [0..400001] of int64;
v:array [0..400001] of boolean;
bo:boolean;
procedure add(u,v,z:longint);
begin
inc(nm);
with a[nm] do
begin
x:=u; y:=v; w:=z;
next:=ls[u];
ls[u]:=nm;
end;
end;
procedure init;
var
i,u,v,z:longint;
begin
readln(n,k);
for k:=1 to k do
begin
readln(z,u,v);
case z of
1:begin
add(u,v,0);
add(v,u,0);
end;
2:begin
if u=v then
begin
write('-1');
halt;
end;
add(u,v,1);
end;
3:add(v,u,0);
4:begin
if u=v then
begin
write('-1');
halt;
end;
add(v,u,1);
end;
5:add(u,v,0);
end;
end;
for i:=1 to n do
add(0,i,1);
bo:=false;
end;
procedure spfa;
var
i,t,x:longint;
begin
fillchar(d,sizeof(d),0);
t:=1;
d[1]:=0; st[1]:=0; v[0]:=true;
while t<>0 do
begin
x:=st[t]; dec(t);
i:=ls[x];
while i<>0 do
begin
if d[a[i].y]<d[x]+a[i].w then
begin
d[a[i].y]:=d[x]+a[i].w;
if not v[a[i].y] then
begin
v[a[i].y]:=true;
inc(t);
st[t]:=a[i].y;
inc(len[a[i].y]);
end;
if len[a[i].y]>n then
begin
bo:=true;
exit;
end;
end;
i:=a[i].next;
end;
v[x]:=false;
end;
end;
procedure print;
var
i:longint;
begin
ans:=0;
for i:=1 to n do
ans:=ans+d[i];
write(ans);
end;
begin
init;
spfa;
if bo then write('-1') else print;
end.