题意:
N头牛M个棚,每头牛对每个棚都有喜爱顺序
每个棚都有自己的容量
问你怎么分配使得所有牛的喜爱程度差距最小
思路:
l r表示一段喜爱程度的范围
建图就按l 到 r里的棚子建
然后两个标移动从头到尾就可以扫出最小值了
/* *********************************************** Author :devil Created Time :2016/5/17 22:28:45 ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <stdlib.h> using namespace std; const int N=1010; const int M=22; const int inf=0x3f3f3f3f; int n,m,l,r,mid,mp[N][N],can[M]; bool vis[M]; vector<int>eg[N],isin[M]; bool Find(int u) { for(int i=0; i<eg[u].size(); i++) { int v=eg[u][i]; if(!vis[v]) { vis[v]=1; if(isin[v].size()<can[v]) { isin[v].push_back(u); return 1; } for(int j=0; j<isin[v].size(); j++) { if(Find(isin[v][j])) { isin[v][j]=u; return 1; } } } } return 0; } bool maxmatch() { for(int i=1; i<=n; i++) eg[i].clear(); for(int i=1;i<=m;i++) isin[i].clear(); for(int i=1;i<=n;i++) for(int j=l;j<=r;j++) eg[i].push_back(mp[i][j]); for(int i=1; i<=n; i++) { memset(vis,0,sizeof(vis)); if(!Find(i)) return 0; } return 1; } int main() { //freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) scanf("%d",&mp[i][j]); for(int i=1;i<=m;i++) scanf("%d",&can[i]); l=r=1; int ans=inf; while(l<=r&&r<=m) { if(maxmatch()) { ans=min(ans,r-l+1); l++; } else r++; } printf("%d ",ans); } return 0; }