题意:
大概就是说要把n个人分到m个个组中去,但是要求分组中人数最大的那个组的人数要尽量小。
题解:
我们二分枚举答案,然后通过多重匹配判断是否可行。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<map> #include<set> #define B(x) (1<<(x)) using namespace std; typedef long long ll; void cmax(int& a,int b){ if(b>a)a=b; } void cmin(int& a,int b){ if(b<a)a=b; } void cmax(ll& a,ll b){ if(b>a)a=b; } void cmin(ll& a,ll b){ if(b<a)a=b; } void add(int& a,int b,int mod){ a=(a+b)%mod; } void add(ll& a,ll b,ll mod){ a=(a+b)%mod; } const int oo=0x3f3f3f3f; const int MOD=1000000007; const int maxn=1100; const int maxm=11000000; int vis[maxn]; int mat[maxn][maxn],num[maxn]; int n,m; struct EDGE{ int v,next; }E[maxm]; int head[maxn],tol,mid; void Init(){ memset(head,-1,sizeof head); tol=0; } void add_edge(int u,int v){ E[tol].v=v; E[tol].next=head[u]; head[u]=tol++; } int dfs(int u){ for(int i=head[u];i!=-1;i=E[i].next){ int v=E[i].v; if(!vis[v]){ vis[v]=1; if(num[v]<mid){ mat[v][++num[v]]=u; return 1; }else{ for(int i=1;i<=num[v];i++) if(dfs(mat[v][i])){ mat[v][i]=u; return 1; } } } } return 0; } int Match(){ memset(num,0,sizeof num); for(int i=1;i<=n;i++){ memset(vis,0,sizeof vis); if(!dfs(i))return 0; } return 1; } bool read(int &num) { char in; bool neg=false; while(((in=getchar()) > '9' || in<'0') && in!='-') ; if(in=='-') { neg=true; while((in=getchar()) >'9' || in<'0'); } num=in-'0'; while(in=getchar(),in>='0'&&in<='9') num*=10,num+=in-'0'; if(in=='\n')return false; if(neg) num=0-num; return true; } map<string,int>had; char str[maxn]; int main(){ //freopen("E:\\read.txt","r",stdin); int u,v,cnt; while(scanf("%d %d",&n,&m)){ if(n==0&&m==0)break; Init(); had.clear(); for(int i=1;i<=n;i++){ scanf("%s",str); u=i; while(1){ bool f=read(v); add_edge(u,v); if(!f)break; } } int l=0,r=n; while(l<r){ mid=(l+r)>>1; if(Match()) r=mid; else l=mid+1; } printf("%d\n",r); } return 0; }