题目大意

nn 个人 mm 个活动,告诉你每一个人对于活动喜欢程度的排序,你可以鸽掉一些活动。如果一个最喜欢的活动被鸽了,那么他就会参加次喜欢的,依次类推直到参加为止。

求参加人数最多的那个项目,参加人数最少是多少。

思路

做法

首先模拟出每一个活动的参加人数,依次将人数最多的活动鸽掉,一遍鸽一遍统计最小值。

理由

假设你已经鸽掉了一些活动,你么现在总能找到一个参加人数最多的项目,假设这个项目是第 xx 个项目。如果将非 xx 的项目鸽掉,那么参加第 xx 个项目的人就并不会减少反而还会增加,这对将整体的最大值减小是没有任何效果的。

假设你鸽掉了第 xx 个项目,那么你肯定就又可以找到一个参加人数是最多的项目,假设是第 yy 个项目。那么如果不鸽掉第 yy 个项目与前面鸽掉第 xx 个项目的效果其实是一样的。所以在这次操作就只能将 yy 鸽掉,否则就没有意义。

AC Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=305;
int n,m,a[N][N],s[N],top[N],ans=1e18;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
			top[i]=1;
		}
	}
	for(int i=1;i<=n;i++){
		s[a[i][1]]++;
	}
	for(int i=1,p,mmax;i<=m;i++){
		mmax=0;
		for(int j=1;j<=m;j++){
			if(s[j]>mmax){
				mmax=s[j];
				p=j;
			}
		}
		ans=min(ans,mmax);
		s[p]=-1;
		for(int j=1;j<=n;j++){
			bool flag=0;
			while(s[a[j][top[j]]]==-1){
				top[j]++;
				flag=1;
			}
			if(flag){
				s[a[j][top[j]]]++;
			}
		}
	}
	cout<<ans<<'\n';
	return 0;
}