poj3189Steady Cow Assignment

题意:有n头牛,b个牛棚,每头牛心目中对牛棚都有个满意度,而每个牛棚是有容量上限的。问将这些牛全部安排好牛棚后,求其中的最低满意度与最高满意度的差,使得这个差值最小。。。

没有二分,TLE成傻逼委屈。。。。。。。

对于匹配来说就是个多重匹配。

但是建图的话,开始枚举的范围[i,j],然后成傻逼,这里的枚举是n^2的,而且每次枚举后都要来遍建图与匹配,,,,,时间是爆炸的。。。

后面两个是不能省的,只能是想办法减少前面的范围枚举方法,枚举范围长度再枚举区间。。。

/*****************************************
Author      :Crazy_AC(JamesQi)
Time        :2015
File Name   :
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
typedef pair<ii,int> iii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 1010;
int n, b, maxR;
int g[N][25];
int top[25];
int num[N];
int cy[25][N];
bool vis[N];
bool dfs(int u,int l) {
	for (int i = l;i <= l + maxR - 1;++i) {
		if (!vis[g[u][i]]) {
			vis[g[u][i]] = true;
			if (num[g[u][i]] < top[g[u][i]]) {
				cy[g[u][i]][++num[g[u][i]]] = u;
				return true;
			}
			for (int j = 1;j <= num[g[u][i]];++j) {
				if (dfs(cy[g[u][i]][j], l)) {
					cy[g[u][i]][j] = u;
					return true;
				}
			}
		}
	}
	return false;
}
int hungary() {
	for (int l = 1;l <= b - maxR + 1;++l) {
		int ans = 0;
		memset(num, 0,sizeof num);
		for (int i = 1;i <= n;++i) {
			memset(vis, false,sizeof vis);
			if (dfs(i, l)) ans++;
		}
		if (ans == n) return 1;
	}
	return 0;
}
int Binary() {
	int ans = 0;
	int low = 1,high = b;
	while(low <= high) {
		int mid = (low + high) >> 1;
		maxR = mid;
		if (hungary()) {
			ans = mid;
			high = mid - 1;
		}else low = mid + 1;
	}
	return ans;
}
int main()
{	
	// freopen("in.txt","r",stdin);
	// freopen("out.txt","w",stdout);
	while(~scanf("%d%d",&n,&b)) {
		for (int i = 1;i <= n;++i) {
			for (int j = 1;j <= b;++j) {
				scanf("%d",&g[i][j]);
			}
		}
		for (int i = 1;i <= b;++i)
			scanf("%d",&top[i]);
		printf("%d\n", Binary());
	}
	return 0;
}


你可能感兴趣的:(poj,二分,多重匹配)