码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 2330: [SCOI2011]糖果 差分约束系统

时间:2016-05-07 09:56:18      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:

题意:幼儿园里有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.


bzoj 2330: [SCOI2011]糖果 差分约束系统

标签:

原文地址:http://blog.csdn.net/qq_33229466/article/details/51334204

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!