POJ 2699 最大流(锦标赛问题)

题意:

有n(n<=10)个竞赛者,进行了n*(n-1)/2次的比赛。已知每一个竞赛者在比赛中胜利的次数a1、a2、a3........an。(次序列是从小到大排序的),问你这n个人中最强的竞赛者最多有几个。(如果这个竞赛者胜利的次数最多或这个竞赛者打败了所有胜利次数比他多的竞赛者,那么这个竞赛者就是最强的。其中每两个人有且仅进行一场比赛。)

题解:

这个题简直太绝了!我只想对了一半,最后还是看了题解。。。

做法大概就是二分枚举最强者的个数(数量比较少,就直接枚举了。),越胜场多的成为强者的几率越高。所以枚举最强的k个人就是胜场最多的k个人

若a,b(a,b都属于枚举的最强者的集合)之间的比赛为c,且a的胜场数小于b的胜场数,则a向c连容量1的边;  表示a必须战胜b,否则a就不可能是最强者

对于其他的a,b和c,a,b分别向c连一条容量为1的边;  表示a,b谁赢谁输都无所谓

S向所有人连容量为此人胜场数的边,比赛c向T连容量1的边

最大流如果和比赛数目相等说明可以有k个人都是最强者

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <algorithm>
  5 #include <iostream>
  6 
  7 #define N 400
  8 #define M 100010
  9 #define INF 1e9
 10 
 11 using namespace std;
 12 
 13 int head[N],next[M],to[M],len[M];
 14 int layer[N],q[M*10],num[N][N],win[N];
 15 int n,cnt,S,T,sm,cas;
 16 
 17 inline void add(int u,int v,int w)
 18 {
 19     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
 20     to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
 21 }
 22 
 23 inline void read()
 24 {
 25     char str[100];
 26     cin.getline(str,90);
 27     int slen=strlen(str);
 28     n=0;
 29     for(int i=0;i<slen;i++)
 30         if(str[i]>='0'&&str[i]<='9')
 31             win[++n]=str[i]-'0';
 32     sm=0;
 33     for(int i=1;i<=n;i++)
 34         for(int j=i+1;j<=n;j++)
 35             num[i][j]=++sm;
 36     S=0; T=n+sm+1;
 37 }
 38 
 39 inline void build(int bs)
 40 {
 41     memset(head,-1,sizeof head); cnt=0;
 42     for(int i=1;i<=n;i++)
 43     {
 44         add(S,i,win[i]);
 45         for(int j=i+1;j<=n;j++)
 46         {
 47             if(i>=bs&&win[i]!=win[j]) add(i,n+num[i][j],1);
 48             else add(i,n+num[i][j],1),add(j,n+num[i][j],1);
 49             add(num[i][j]+n,T,1);
 50         }
 51     }
 52 }
 53 
 54 inline bool bfs()
 55 {
 56     memset(layer,-1,sizeof layer);
 57     int h=1,t=2,sta;
 58     q[1]=S; layer[S]=0;
 59     while(h<t)
 60     {
 61         sta=q[h++];
 62         for(int i=head[sta];~i;i=next[i])
 63             if(len[i]&&layer[to[i]]<0)
 64             {
 65                 layer[to[i]]=layer[sta]+1;
 66                 q[t++]=to[i];
 67             }
 68     }
 69     return layer[T]!=-1;
 70 }
 71 
 72 inline int find(int u,int cur_flow)
 73 {
 74     if(u==T) return cur_flow;
 75     int res=0,tmp;
 76     for(int i=head[u];~i&&res<cur_flow;i=next[i])
 77         if(len[i]&&layer[to[i]]==layer[u]+1)
 78         {
 79             tmp=find(to[i],min(cur_flow-res,len[i]));
 80             len[i]-=tmp; len[i^1]+=tmp; res+=tmp;
 81         }
 82     if(!res) layer[u]=-1;
 83     return res;
 84 }
 85 
 86 inline int dinic()
 87 {
 88     int ans=0;
 89     while(bfs()) ans+=find(S,INF);
 90     return ans;
 91 }
 92     
 93 
 94 inline void go()
 95 {
 96     for(int i=n;i>=1;i--)
 97     {
 98         build(i);
 99         if(dinic()>=sm) continue;
100         printf("%d\n",n-i);
101         return;
102     }
103     printf("%d\n",n);
104 }
105 
106 int main()
107 {
108     scanf("%d\n",&cas);
109     while(cas--) read(),go();
110     return 0;
111 }
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2850366.html