【POJ2699】The Maximum Number of Strong Kings(二分,最大流)

题意:

有n个队伍,两两都有比赛

知道最后每支队伍获胜的场数

求最多有多少队伍,他们战胜了所有获胜场数比自己多的队伍,这些队伍被称为SK

N<=50

思路:把每个队伍和它们两两之间的比赛都当做点,判断最大流是否满流即可

S——>队伍 a[i]

队伍 ——>比赛 1

比赛——>T 1

i号队伍是SK:如果j为SK且a[i]>a[j]则j必胜,如果a[i]<a[j]则i必胜 只要必胜者向他们之间的比赛连1条边即可

                   如果j不为SK,胜负未知,两个点都向他们之间的比赛连1条边

i号队伍不是SK:对于所有的队伍都胜负未知,同上处理

最暴力的思想就是枚举每个队伍作为SK的可能性再根据得分情况连边,其实也能过

不过可以证明一定存在一种方案,使得SK是排序后得分最多的那些队伍

二分或枚举答案即可

证明见http://blog.csdn.net/sdj222555/article/details/7797257

  1 var head,a:array[1..300]of longint;
  2     fan:array[1..200000]of longint;
  3     vet,next,len,dis,gap,flag:array[0..20000]of longint;
  4     num:array[1..100,1..100]of longint;
  5     n,i,j,tot,l,r,mid,last,s,source,src,cas,v,k:longint;
  6     ch:ansistring;
  7 
  8 function min(x,y:longint):longint;
  9 begin
 10  if x<y then exit(x);
 11  exit(y);
 12 end;
 13 
 14 procedure add(a,b,c:longint);
 15 begin
 16 
 17  inc(tot);
 18  next[tot]:=head[a];
 19  vet[tot]:=b;
 20  len[tot]:=c;
 21  head[a]:=tot;
 22 
 23  inc(tot);
 24  next[tot]:=head[b];
 25  vet[tot]:=a;
 26  len[tot]:=0;
 27  head[b]:=tot;
 28 
 29 end;
 30 
 31 procedure swap(var x,y:longint);
 32 var t:longint;
 33 begin
 34  t:=x; x:=y; y:=t;
 35 end;
 36 
 37 procedure qsort(l,r:longint);
 38 var i,j,mid:longint;
 39 begin
 40  i:=l; j:=r; mid:=a[(l+r)>>1];
 41  repeat
 42   while mid<a[i] do inc(i);
 43   while mid>a[j] do dec(j);
 44   if i<=j then
 45   begin
 46    swap(a[i],a[j]);
 47    inc(i); dec(j);
 48   end;
 49  until i>j;
 50  if l<j then qsort(l,j);
 51  if i<r then qsort(i,r);
 52 end;
 53 
 54 function dfs(u,aug:longint):longint;
 55 var e,v,t,val,flow:longint;
 56 begin
 57  if u=src then exit(aug);
 58  e:=head[u]; val:=s-1; flow:=0;
 59  while e<>0 do
 60  begin
 61   v:=vet[e];
 62   if len[e]>0 then
 63   begin
 64    if dis[u]=dis[v]+1 then
 65    begin
 66     t:=dfs(v,min(len[e],aug-flow));
 67     len[e]:=len[e]-t;
 68     len[fan[e]]:=len[fan[e]]+t;
 69     flow:=flow+t;
 70     if dis[source]>=s then exit(flow);
 71     if aug=flow then break;
 72    end;
 73    val:=min(val,dis[v]);
 74   end;
 75   e:=next[e];
 76  end;
 77  if flow=0 then
 78  begin
 79   dec(gap[dis[u]]);
 80   if gap[dis[u]]=0 then dis[source]:=s;
 81   dis[u]:=val+1;
 82   inc(gap[dis[u]]);
 83  end;
 84  exit(flow);
 85 end;
 86 
 87 function maxflow:longint;
 88 var ans:longint;
 89 begin
 90  fillchar(gap,sizeof(gap),0);
 91  fillchar(dis,sizeof(dis),0);
 92  gap[0]:=s; ans:=0;
 93  while dis[source]<s do ans:=ans+dfs(source,maxlongint);
 94  exit(ans);
 95 end;
 96 
 97 procedure build(k:longint);
 98 var i,j:longint;
 99 begin
100  fillchar(flag,sizeof(flag),0);
101  fillchar(head,sizeof(head),0); tot:=0;
102 
103  for i:=1 to k do
104  begin
105   for j:=1 to i-1 do
106   begin
107    flag[num[i,j]]:=1;
108    add(i,num[i,j],1);
109   end;
110   for j:=i+1 to n do
111    if (a[j]<a[i])and(j<=k)and(flag[num[i,j]]=0) then
112    begin
113     flag[num[i,j]]:=1;
114     add(j,num[i,j],1);
115    end
116     else if flag[num[i,j]]=0 then
117     begin
118      flag[num[i,j]]:=1;
119      add(i,num[i,j],1);
120      add(j,num[i,j],1);
121     end;
122  end;
123  for i:=k+1 to n do
124   for j:=1 to n do
125    if (i<>j)and(flag[num[i,j]]=0) then
126    begin
127     add(i,num[i,j],1);
128     add(j,num[i,j],1);
129     flag[num[i,j]]:=1;
130    end;
131  for i:=1 to n do add(source,i,a[i]);
132  for i:=1 to n do
133   for j:=1 to n do
134    if i<j then add(num[i,j],src,1);
135 end;
136 
137 function isok(k:longint):boolean;
138 begin
139  if maxflow=n*(n-1) div 2 then exit(true);
140  exit(false);
141 end;
142 
143 begin
144  assign(input,'poj2699.in'); reset(input);
145  assign(output,'poj2699.out'); rewrite(output);
146  for i:=1 to 200000 do
147   if i mod 2=1 then fan[i]:=i+1
148    else fan[i]:=i-1;
149  readln(cas);
150  for v:=1 to cas do
151  begin
152   fillchar(num,sizeof(num),0);
153   readln(ch); k:=length(ch);
154   fillchar(a,sizeof(a),0); n:=0;
155   i:=0;
156   while i<k do
157   begin
158    inc(i);
159    while (i<k)and(ch[i]=' ') do inc(i);
160    inc(n);
161    while (i<=k)and(ch[i]<>' ') do
162    begin
163     a[n]:=a[n]*10+ord(ch[i])-ord('0');
164     inc(i);
165    end;
166   end;
167 
168   qsort(1,n); s:=n;
169   for i:=1 to n do
170    for j:=1 to n do
171     if i<>j then
172     begin
173      if num[j,i]=0 then
174      begin
175       inc(s); num[i,j]:=s;
176      end
177       else num[i,j]:=num[j,i];
178     end;
179   inc(s); source:=s; inc(s); src:=s;
180 
181   l:=0; r:=n; last:=0;
182   while l<=r do
183   begin
184    mid:=(l+r)>>1;
185    build(mid);
186    if isok(mid) then begin last:=mid; l:=mid+1; end
187     else r:=mid-1;
188   end;
189   writeln(last);
190  end;
191  close(input);
192  close(output);
193 end.
原文地址:https://www.cnblogs.com/myx12345/p/6230568.html