1. 程式人生 > >bzoj 2330: [SCOI2011]糖果 差分約束系統

bzoj 2330: [SCOI2011]糖果 差分約束系統

題意:幼兒園裡有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.