题意:幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
分析:很明显的差分约束系统。
由于是求最小值,所以就要把所有不等式都转换成x-y>=k的形式然后连一条y->x权值为k的边。
后四个操作都很简单,关键是第一个操作。
那么我们就可以把A=B转换成A-B>=0且B-A>=0然后跑最长路最后统计就好啦。
还有就是判断负权(最短路)或正权(最长路)回路的问题,若一个点被松弛了n次以上则为有回路。
有一个很神奇的地方就是加起点到所有点的边的时候要倒着加不然就会T(我也不造为毛)
代码:
const
maxn=100005; maxm=100005; var state,d,last,time:array[0..maxn] of longint; v:array[0..maxn] of boolean; side:array[1..maxm*3] of record x,y,z,next:longint; end; n,m,e:longint; procedure add(x,y,z:longint); begin inc(e); side[e].x:=x; side[e].y:=y; side[e].z:=z; side[e].next:=last[x]; last[x]:=e; end; procedure init; var x,y,z,i:longint; begin readln(n,m); for i:=1 to m do begin readln(z,x,y); case z of 1:begin add(x,y,0); add(y,x,0); end; 2:add(x,y,1); 3:add(y,x,0); 4:add(y,x,1); 5:add(x,y,0); end; end; for i:=n downto 1 do add(0,i,1); end; procedure spfa; var head,tail,i,u:longint; ans:int64; begin for i:=1 to e do with side[i] do if (x=y)and(z>0) then begin writeln(-1); exit; end; head:=0; tail:=1; state[1]:=0; time[0]:=1; fillchar(v,sizeof(v),true); v[0]:=false; repeat inc(head); if head>n+1 then head:=1; u:=state[head]; i:=last[u]; while i>0 do with side[i] do begin if d[x]+z>d[y] then begin inc(time[y]); if time[y]>n then begin writeln(-1); exit; end; d[y]:=d[x]+z; if v[y] then begin v[y]:=false; inc(tail); if tail>n+1 then tail:=1; state[tail]:=y; end; end; i:=next; end; v[u]:=true; until head=tail; ans:=0; for i:=1 to n do ans:=ans+d[i]; writeln(ans); end; begin init; spfa; end.
时间: 2024-10-24 18:45:15