这道题和今年GDKOI的Day2T2很像(然而gdkoi的题用网络流可以A,这道题只能拿30)。

  网址:http://www.lydsy.com/JudgeOnline/problem.php?id=1854

  题目:

  【BZOJ1854】游戏[SCOI2009](神奇贪心+并查集)

   很显然,我们可以立即想到一种解法:如果第i个武器的属性是(a,b),那么就连i->a,i->b两条边,然后就跑网络流。为了确保要从1开始连续攻击,就可以二分答案,用网络流来判断,因为如果能从1打到n,就肯定能从1打到n-1(废话)。判断就是每次只让1~mid的属性值流过去,看一下最后的最大流是否为mid,就知道能不能从1打到mid。

代码:

var f,d,q,x,y:array[0..1000010]of longint;
  a,b,ne:array[0..2000010]of longint;
  n,k,nn,i,j,h,t,p,l,r,m,ans:longint;
procedure add(x,y,z:longint);
begin
  a[p]:=y; b[p]:=z; ne[p]:=f[x]; f[x]:=p; inc(p);
  a[p]:=x; b[p]:=0; ne[p]:=f[y]; f[y]:=p; inc(p);
end;
function dfs(now,ll:longint):longint;
var i,p:longint;
begin
  if now=nn then exit(ll); i:=f[now];
  while i>=0 do begin
    if(b[i]>0)and(d[a[i]]=d[now]+1)then begin
      if ll<b[i] then p:=dfs(a[i],ll)
      else p:=dfs(a[i],b[i]);
      b[i]:=b[i]-p; b[i xor 1]:=b[i xor 1]+p;
      if p>0 then exit(p);
    end;
    i:=ne[i];
  end;
  exit(0);
end;
begin
  read(n);
  for i:=1 to n do read(x[i],y[i]);
  l:=0; r:=10001; nn:=n+10001;
  while l+1<r do begin
    p:=0; m:=(l+r)>>1;
    for i:=0 to nn do f[i]:=-1;
    for i:=1 to n do begin
      add(i,n+x[i],1); add(i,n+y[i],1);
    end;
    for i:=1 to n do add(0,i,1);
    for i:=1 to m do add(n+i,nn,1);
    ans:=0;
    while true do begin
      for i:=0 to nn do d[i]:=0;
      h:=1; t:=1; q[1]:=0; d[0]:=1;
      repeat
        i:=f[q[h]];
        while i>=0 do begin
          if(b[i]>0)and(d[a[i]]=0)then begin
            inc(t); q[t]:=a[i]; d[a[i]]:=d[q[h]]+1;
          end;
          i:=ne[i];
        end;
        inc(h);
      until h>t;
      if d[nn]=0 then break;
      repeat
        p:=dfs(0,1<<25);
        ans:=ans+p;
      until p=0;
    end;
    if m=ans then l:=m else r:=m;
  end;
  writeln(l);
end.
View Code

相关文章:

  • 2022-12-23
  • 2021-11-13
  • 2021-10-08
  • 2021-09-18
  • 2021-11-22
  • 2022-01-01
猜你喜欢
  • 2022-12-23
  • 2021-06-13
  • 2021-10-22
  • 2022-01-06
  • 2021-12-13
相关资源
相似解决方案