题意:给n个递增(不降)的分数,即n支队伍比赛所得的分数,赢一场得一分,输不得分,两两比赛。
找出最多有多少个king,king的意思是他的分数最高或他打败了所有分数比他高的选手。
n<=10
分析:主要是建图怎么建,有n个人,比赛场次有n*(n-1)/2,把每个人和每次比赛看作点。源点到人i,建边add(s,i,score[i]),容量为他的分数,比赛场次到汇点t,建边add(j,t,1);
题目要求最大,那么我们可以从大到小枚举king 的个数。假设枚举到m,那么后面m个人是不是都要打败得分比他多的人,add(i,v,1),v为比赛场次;对于其他的任何人赢都无所谓,add(i,v,1),add(j,v,1);(i,j)两人比赛场次为v。
最后跑最大流,如果是满流,那么答案它。
#include<iostream>
#include<string>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<math.h>
#include<queue>
#include<map>
#include<sstream>
#include<set>
#include<algorithm>
using namespace std;
#define MAXN 505
#define MAXM 505*500
#define LL long long
#define INF 0x7f7f7f7f
const double eps = 1e-10;
struct Edge
{
int from,to,cap,flow;
Edge(int from=0,int to=0,int cap=0,int flow=0):from(from),to(to),cap(cap),flow(flow){}
};
vector<Edge>edges;
vector<int>g[MAXN];
bool vis[MAXN];
int d[MAXN];
int cur[MAXN];
int s,t;
void init()
{
for(int i=0;i<MAXN;i++)
{
g[i].clear();
}
edges.clear();
}
void add(int from,int to,int cap)
{
edges.push_back(Edge(from,to,cap,0));
edges.push_back(Edge(to,from,0,0));
int m=edges.size();
g[from].push_back(m-2);
g[to].push_back(m-1);
}
bool bfs()
{
memset(vis,0,sizeof(vis));
queue<int>q;
q.push(s);
d[s]=0;
vis[s]=1;
while(!q.empty())
{
int tx=q.front();
q.pop();
int sz=g[tx].size();
for(int i=0;i<sz;i++)
{
Edge e=edges[g[tx][i]];
if(!vis[e.to]&&e.cap>e.flow)
{
vis[e.to]=1;
d[e.to]=d[tx]+1;
q.push(e.to);
}
}
}
return vis[t];
}
int dfs(int x,int a)
{
if(x==t||a==0)
return a;
int flow=0,f;
int sz=g[x].size();
for(int &i=cur[x];i<sz;i++)
{
Edge &e=edges[g[x][i]];
if(d[x]+1==d[e.to])
{
f=dfs(e.to,min(a,e.cap-e.flow));
if(f>0)
{
e.flow+=f;
edges[g[x][i]^1].flow-=f;
// Edge E=edges[g[x][i]^1];
flow+=f;
a-=f;
if(a==0)break;
}
}
}
return flow;
}
int maxFlow()
{
int flow=0;
while(bfs())
{
memset(cur,0,sizeof(cur));
flow+=dfs(s,INF);
}
return flow;
}
int score[110],maze[110][110],n,f[110][110];
int main()
{
int i,j;
int cas;
char str[100];
scanf("%d",&cas);
getchar();
while(cas--)
{
int cnt=0;
gets(str);
stringstream ss(str);
int xx;
while(ss>>xx)score[++cnt]=xx;
int k=cnt;
for(i=1;i<=cnt;i++)
{
for(j=i+1;j<=cnt;j++)
{
maze[i][j]=++k;
}
}
int ans;
s=0;t=k+1;
for(ans=cnt;ans>=1;ans--)
{
init();
memset(f,0,sizeof(f));
for(i=1;i<=cnt;i++)
{
for(j=i+1;j<=cnt;j++)
{
add(maze[i][j],t,1);
}
}
for(i=1;i<=cnt;i++)
add(s,i,score[i]);
for(i=cnt-ans+1;i<=cnt;i++)
{
for(j=i+1;j<=cnt;j++)
{
if(score[i]<score[j])
{
f[i][j]=1;
add(i,maze[i][j],1);
}
}
}
for(i=1;i<=cnt;i++)
{
for(j=i+1;j<=cnt;j++)
{
if(!f[i][j])
{
add(i,maze[i][j],1);
add(j,maze[i][j],1);
}
}
}
int temp=maxFlow();
//cout<<ans<<" "<<temp<<endl;
if(temp==cnt*(cnt-1)/2)
{
printf("%d\n",ans);
break;
}
}
}
return 0;
}