题目链接
https://agc018.contest.atcoder.jp/tasks/agc018_b
题意简述
有 n n n个人 m m m种运动,每个人给出了喜好每种运动的顺序,越靠前表示越喜欢。现在你需要选取一些运动,每个人会选取这些运动里他最喜欢的那个参加,求参加运动人数最多的运动的参加人数最少是多少。
题解
如果一个运动被 k k k个人选取了,那么删掉其他的运动,这个运动参加的人数不会变少。那么每次删掉参加人数最多的那些运动,取每次删的那种运动人数最小值即可。
代码
#include <cstdio>
#include <algorithm>
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int maxn=300;
const int inf=0x3f3f3f3f;
int n,m,a[maxn+4][maxn+4],in[maxn+4],mx[maxn+4],ans;
int main()
{
n=read();
m=read();
for(int i=1; i<=n; ++i)
{
for(int j=1; j<=m; ++j)
{
a[i][j]=read();
}
}
ans=n;
int cnt=0;
while(cnt<m)
{
for(int j=1; j<=m; ++j)
{
mx[j]=0;
}
for(int j=1; j<=n; ++j)
{
int nowi=-1;
for(int k=1; k<=m; ++k)
{
if(!in[a[j][k]])
{
nowi=a[j][k];
break;
}
}
++mx[nowi];
}
int now=-1;
for(int j=1; j<=m; ++j)
{
if((!in[j])&&(mx[j]>now))
{
now=mx[j];
}
}
ans=std::min(ans,now);
for(int j=1; j<=m; ++j)
{
if((!in[j])&&(mx[j]==now))
{
in[j]=1;
++cnt;
}
}
}
printf("%d\n",ans);
return 0;
}