分糖果 5.0升级版

题目描述

幼儿园里有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.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值