题意:有一些牛和牛棚(有容量),每头牛对牛棚有喜好程度,要求每头牛都有一个棚子的情况下,找最小的喜好程度之差
题解:题意是真的恶心,wa了好久才发现没读懂,一直以为输入 的是排名,其实是牛棚标号,从1到m。用最大流一直tle,无奈还是用匈牙利算法,对于匈牙利算法求解二分图多重匹配,可以用一个容量数组来操作,如果容量没满,那么直接放进来,否则就遍历一遍,看是否有可能找到增广路,这题是二分差值,然后通过遍历找满足条件的最小结果。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 20090717 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-12; const int N=3000+10,maxn=20000+10,inf=0x3f3f3f3f; int ra[N][30],c[30],num[30]; bool vis[30]; struct edge{ int to,Next; }e[maxn<<2]; int n,m,ans[30][N]; int cnt,head[N]; void add(int u,int v) { // cout<<u<<" "<<v<<endl; e[cnt].to=v; e[cnt].Next=head[u]; head[u]=cnt++; } bool match(int x) { for(int i=head[x];~i;i=e[i].Next) { int y=e[i].to; if(vis[y])continue; vis[y]=1; if(num[y]<c[y]) { ans[y][++num[y]]=x; return 1; } else { for(int j=1;j<=c[y];j++) { if(match(ans[y][j])) { ans[y][j]=x; return 1; } } } } return 0; } void init() { cnt=0; for(int i=1;i<=n;i++)head[i]=-1; for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) ans[i][j]=0; for(int i=1;i<=m;i++)num[i]=0; } bool isok(int x) { for(int k=0; k+x<=m; k++) { init(); for(int i=1; i<=n; i++) for(int j=k+1; j<=k+x; j++) add(i,ra[i][j]); int res=0; for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++)vis[j]=0; if(match(i))res++; } if(res==n) { return 1; } } return 0; } int main() { /*ios::sync_with_stdio(false); cin.tie(0);*/ while(~scanf("%d%d",&n,&m)) { for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) scanf("%d",&ra[i][j]); for(int i=1; i<=m; i++)scanf("%d",&c[i]); int l=0,r=m+1; while(r-l>1) { int mid=(l+r)/2; if(isok(mid))r=mid; else l=mid; } printf("%d ",r); } return 0; } /******************** 6 6 2 3 4 5 6 1 3 6 4 5 1 2 2 6 4 5 1 3 3 6 2 5 1 4 1 3 4 2 6 5 2 3 4 5 1 6 2 2 2 2 2 2 ********************/