【USACO 2857】 Steady Cow Assignment

本文介绍了一种结合二分查找与最大流算法解决特定问题的方法。通过二分答案来缩小搜索范围,并利用最大流算法验证解的可行性。适用于求解资源分配问题,如在给定条件下寻找最优分配方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目链接】

            点击打开链接

【算法】

           二分答案,check的时候跑最大流,即可

【代码】

         

#include<bits/stdc++.h>
using namespace std;
#define MAXN 2000
#define MAXB 1000

int i,j,low,high,mid,st,ed,N,B,tot,ans,tmp;
int h[MAXN+MAXB],U[MAXN*MAXB],V[MAXN*MAXB],
   W[MAXN*MAXB],Head[MAXN*MAXB],Next[MAXN*MAXB],
	 other[MAXN*MAXB],v[MAXB+10],a[MAXN+10][MAXB+10];
	 
template <typename T> void read(T &x) {
		int f=1; char c = getchar(); x=0;
		for (; !isdigit(c); c = getchar()) { if (c=='-') f = -f; }
		for (; isdigit(c); c = getchar()) x=x*10+c-'0';
		x*=f;
}
template <typename T> inline void write(T x) {
		if (x < 0) { putchar('-'); x = -x; }
		if (x > 9) write(x/10);
		putchar(x % 10 + '0');	
}

template <typename T> inline void writeln(T x) {
		write(x);
		puts("");	
}

inline void add(int a,int b,int c) {
		++tot;
		U[tot] = a; V[tot] = b; W[tot] = c;
		Next[tot] = Head[a]; Head[a] = tot; 
		other[tot] = ++tot;
		U[tot] = b; V[tot] = a; W[tot] = 0;
		Next[tot] = Head[b]; Head[b] = tot;
		other[tot] = tot - 1;	
}

inline bool bfs() {
		int i,x,y;
		queue<int> q;
		memset(h,0,sizeof(h));
		h[st] = 1; q.push(st);
		while (!q.empty()) {
				x = q.front(); q.pop();
				for (i = Head[x]; i; i = Next[i]) {
						y = V[i];
						if ((W[i] > 0) && (!h[y])) {
								h[y] = h[x] + 1;
								q.push(y);
						}
				}
		}
		if (h[ed]) return true;
		else return false;
}

inline int maxflow(int x,int f) {
		int i,t,y,sum=0;
		if (x == ed) return f;
		for (i = Head[x]; i; i = Next[i]) {
				y = V[i];
				if ((W[i] > 0) && (h[y] == h[x] + 1) && (sum < f)) {
						sum += (t = maxflow(y,min(W[i],f-sum)));
						W[i] -= t; W[other[i]] += t;
				} 	
		}	
		if (!sum) h[x] = 0;
		return sum;
}

inline bool check(int ml) {
		int i,j,l,r,sum;	
		for (l = 1; l <= N - ml + 1; l++) {
				r = l + ml - 1;
				for (i = 1; i <= tot; i++) Head[i] = 0;
				tot = 0;
				for (i = 1; i <= N; i++) add(st,i,1);
				for (i = 1; i <= B; i++) add(i+N,ed,v[i]);
				for (i = 1; i <= N; i++) {
						for (j = 1; j <= B; j++) {
								if ((a[i][j] >= l) && (a[i][j] <= r))
										add(i,j+N,1);
						}
				}
				sum = 0;
				while (bfs()) {
						sum += maxflow(st,N);
				}
				if (sum == N) return true;
		}
		return false;
}

int main() {
		
		read(N); read(B);
		st = N + B + 1; ed = st + 1;
		
		for (i = 1; i <= N; i++) {
				for (j = 1; j <= B; j++) {
						read(tmp);
						a[i][tmp] = j;
				}	
		} 
		for (i = 1; i <= B; i++) read(v[i]);
		
		low = 0; high = B;
		while (low <= high) {
				mid = (low + high) / 2;
				if (check(mid)) {
						high = mid - 1;
						ans = mid;
				} else 
						low = mid + 1;
		}
		writeln(ans);
		
		return 0;
	
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值