【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.
null