这道题是个不错的题
【题意】
n个人比赛, 两两比,共n*(n-1), 赢得1分, n<=10(这给了我们枚举的暗示)
如果一个人打败了所有比自己分数高的人, 或者他本身就是分数最高的, 那么他就是
StrongKing
可能有多个Strong King, 现在按非降的顺序给你每个人的得分(不难道想到容量把), 问
Strong King最多能有几个
【解答】
一般遇到竞赛图,网络流的可能性较大,因为竞赛图中的条件都与点的度数有关。
建图:二分图,左边是人,右边是比赛,源点到人连容量为score[i]的边,汇点到比赛连
容量为1的边。然后枚举答案ans,由于分数越高的人成为
strongking的可能性较大(我一开始没有意识到这点,还想用2^10的枚举),于是让后
ans个人成为strongking,然后对这ans个人中的i,j,如果score[i]<score[j]则i像match[i]
[j]连容量为一的边。然后对剩余的比赛match[i][j],让i,j向点match[i][j]连容量为1的边。
当maxflow==n*(n-1)/2时,则ans为解
#include <iostream>
#include <cstring>
#include <string>
#include <sstream>
using namespace std;
const int oo=200000;
struct edge
{
int x,y,f,next,op;
}e[2000];
int g[20],m[20][20],h[100],d[100],p[100],now[100],num[100],f[100];
int n,s,t,tot,tt;
void ins(int x,int y,int f)
{
e[++tot].x=x;e[tot].y=y;
e[tot].next=h[x];e[tot].f=f;
h[x]=tot;
e[++tot].x=y;e[tot].y=x;
e[tot].next=h[y];e[tot].f=0;
h[y]=tot;
e[tot].op=tot-1;e[tot-1].op=tot;
}
void build(int num)
{
tot=0;
int i,j;
memset(f,0,sizeof(f));
memset(h,0,sizeof(h));
for (i=1;i<=n;i++)
ins(s,i,g[i]);
for (i=1;i<=tt;i++)
ins(i+n,t,1);
for (i=n-num+1;i<=n;i++)
for (j=i+1;j<=n;j++)
if (g[j]>g[i])
{
f[m[i][j]]=1;
ins(i,m[i][j]+n,1);
}
for (i=1;i<=n;i++)
for (j=i+1;j<=n;j++)
if (!f[m[i][j]])
{
ins(i,m[i][j]+n,1);
ins(j,m[i][j]+n,1);
}
}
int isap()
{
int flow=0,aug=oo,u,v,tmp,i,j,ff;
for (i=0;i<=t;i++)
{
d[i]=0;p[i]=-1;
num[i]=0;now[i]=h[i];
}
num[0]=t+1;u=s;
while (d[s]<t+1)
{
for (ff=0,i=now[u];i;i=e[i].next)
{
v=e[i].y;
if (e[i].f && d[u]==d[v]+1)
{
ff=1;
if (e[i].f<aug) aug=e[i].f;
p[v]=i;now[u]=i;
u=v;
if (u==t)
{
flow+=aug;
while (u!=s)
{
j=p[u];
e[j].f-=aug;
e[e[j].op].f+=aug;
u=e[j].x;
}
aug=oo;
}
break;
}
}
if (ff) continue;
num[d[u]]--;
if (!num[d[u]]) return flow;
tmp=t+1;
for (i=h[u];i;i=e[i].next)
{
v=e[i].y;
if (e[i].f && d[v]<tmp)
{
tmp=d[v];now[u]=i;
}
}
d[u]=tmp+1;
num[d[u]]++;
if (u!=s) u=e[p[u]].x;
}
return flow;
}
int main()
{
freopen("pin.txt","r",stdin);
freopen("pou.txt","w",stdout);
char str[40];
int i,j,cc;
cin >> cc;
getchar();
while (cc--)
{
gets(str);
stringstream ss(str);
n=0;
while (ss >> j)
g[++n]=j;
tt=0;
for (i=1;i<=n;i++)
for (j=i+1;j<=n;j++)
m[i][j]=++tt;
s=0;t=tt+n+1;
for (i=n;i>1;i--)
{
build(i);
if (isap()==(n*(n-1))/2) break;
}
cout << i << endl;
}
return 0;
}