2018 山东省ACM省赛B题Bullet (二分+二分图最大匹配)

Description
In GGO, a world dominated by gun and steel, players are fighting for the honor of being the strongest gunmen. Player Shino is a sniper, and her aimed shot kills one monster at a time. Now she is in an n×n map, and there are monsters in some grids. Each monster has an experience. As a master, however, Shino has a strange self-restrain. She would kill at most one monster in a column, and also at most one in a row. Now she wants to know how to get max experience, under the premise of killing as many monsters as possible.

Input
The first line contains an integer n(n≤500)
Then n lines follow. In each line there are n integers, and Aijrepresents the experience of the monster at grid(i,j). If Aij=0, there is no monster at grid(i,j).
Aij≤109
Output
One integer, the value of max experience.

Samples
Input Copy
2
2 0
1 8
Output
2
题目大意
给你一个n*n的矩阵,在矩阵中选一个数,选择后该点所在的行和列都不能在选择,然后问你选出的一堆数中的最小值最大是多少

解题思路:
首先,最小值最大化我们可以采用二分答案;
然后 ,如何check 答案?
因为每行每列中只能选一个数字,用二分图行列模型求出最大匹配时多少,记为top

因为我们二分的是 取数方案中的数的最小值,所以我们在建图的时候如果点的权值大于mid我们建一条边,然后跑一个二分图最大匹配,看看在最小值为mid的时候最大匹配与top相等不相等, 继续二分答案;

Code

#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>

using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef unsigned long long ull;
const int inf = 0x3f3f3f3f;
const int maxn = 5e5+ 7;
const ll mod = 1000000007;

#define mst(x, a) memset( x,a,sizeof(x) )
#define rep(i, a, b) for(int i=(a);i<=(b);++i)
#define dep(i, a, b) for(int i=(a);i>=(b);--i)

ll read() {
    
    
	ll x=0;
	char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}

void out(ll x) {
    
    
	int stackk[40];
	if (x < 0) {
    
    
		putchar('-');
		x = -x;
	}
	if (!x) {
    
    
		putchar('0');
		return;
	}
	int top = 0;
	while (x) stackk[++top] = x % 10, x /= 10;
	while (top) putchar(stackk[top--] + '0');
}
ll n,a[666][666],link[666][666],use[666],g[666],top,tmp;
int find(ll x) {
    
    
	for(int i=1 ; i<=n ; i++) {
    
    
		if(link[x][i]&&use[i]==0) {
    
    
			use[i]=1;
			if(g[i]==0||find(g[i])) {
    
    
				g[i]=x;
				return 1;
			}
		}
	}
	return 0;
}

int check(ll mid) {
    
    
	ll temp=0;
	mst(g,0);
	for(int i=1 ; i<=n ; i++) {
    
    
		mst(use,0);
		if(find(i)) temp++;
	}
	if(temp==top) return 1;
	return 0;
}
int main() {
    
    
	n=read();
	ll  tt=0;
	for(int i=1 ; i<=n ; i++) {
    
    
		for(int j=1 ; j<=n ; j++) {
    
    
			a[i][j]=read();
			if(a[i][j]) link[i][j]=1;
			tt=max(tt,a[i][j]);
		}
	}
	if(tt==0) {
    
    
		puts("0");
		return 0;
	}
	for(int i=1 ; i<=n ; i++) {
    
    
		mst(use,0);
		if(find(i)) top++;
	}
	ll l=1,r=tt,ans;
	while(l<=r) {
    
    
		ll mid=(l+r)>>1;
		mst(link,0);
		rep(i,1,n) rep(j,1,n)	if(a[i][j]>=mid&&mid) link[i][j]=1;
		if(check(mid)) {
    
    
			l=mid+1;
			ans=mid;
		} else  r=mid-1;
	}
	out(ans);
	return 0;
}
/*

*/

猜你喜欢

转载自blog.csdn.net/wmy0536/article/details/109152791
今日推荐