标签:
Description
Input
Output
Sample Input
2 3 2 0 3 2 1 1 3 0 3 2 0 2 3 0 1 0 1 2 1 0 2 1 0 0 2 0
Sample Output
2
题目大意:给你K个挤奶点,C头牛,每个挤奶点能最多挤K头牛。下面是矩阵,行和列都表示K个挤奶点,C头牛。矩阵A(i,j)表示i到j的距离。距离都为正值,如果出现0,则表示不直接连通。数据保证有解。问你让这m头牛都能挤奶的条件下,最远的牛最少要走多远。
解题思路:二分枚举距离,每次根据枚举的距离,重新构图。每个挤奶点的匹配次数已知。但是这个题目有一点比较坑,就是二分枚举的时候,r应该从最大值INF开始,因为200只是两点之间的直接距离,floyd之后,可能会出现大于200的距离,应该注意。
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
const int INF = 9999999;
const int maxn = 1010;
int Map[maxn][maxn];
int linker[maxn][maxn], used[maxn];
int M;
bool dfs(int u,int rn){
for(int v = 1; v <= rn; v++){
if(used[v] || !Map[u][v]){
continue;
}
used[v] = 1;
if(linker[v][0] < M){
linker[v][++linker[v][0]] = u;
return true;
}else{
for(int j = 1; j <= linker[v][0]; j++){
if(dfs(linker[v][j],rn)){
linker[v][j] = u;
return true;
}
}
}
}
return false;
}
bool Hungary(int ln,int rn){
int ret = 0;
for(int i = 0; i <= rn; i++){
linker[i][0] = 0;
}
for(int i = 1; i <= ln; i++){
memset(used,0,sizeof(used));
if(dfs(i,rn)){
ret++;
}
}
if(ln == ret){
return true;
}
return false;
}
int main(){
int K, C;
int matrix[500][500];
while(scanf("%d%d%d",&K,&C,&M)!=EOF){
int nn = K + C;
for(int i = 1; i <= nn; i++){
for(int j = 1; j <= nn; j++){
scanf("%d",&matrix[i][j]);
if(matrix[i][j] == 0){
matrix[i][j] = INF;
}
}
}
for(int k = 1; k <= nn; k++){
for(int i = 1; i <= nn; i++){
for(int j = 1; j <= nn; j++){
if(matrix[i][j] > matrix[i][k] + matrix[k][j]){
matrix[i][j] = matrix[i][k] + matrix[k][j];
}
}
}
}
int l = 1, r = INF, ans;
while(l <= r){ //不会写二分,错了n多次 ORZ
int mid = (l+r)/2;
memset(Map,0,sizeof(Map));
for(int i = K + 1; i <= nn; i++){
for(int j = 1; j <= K; j++){
if(matrix[i][j] <= mid){
Map[i-K][j] = 1;
}
}
}
if(Hungary(C,K)){
r = mid - 1;
ans = mid;
}else{
l = mid + 1;
}
}
printf("%d\n",l);
}
return 0;
}
POJ 2112—— Optimal Milking——————【多重匹配、二分枚举答案、floyd预处理】
标签:
原文地址:http://www.cnblogs.com/chengsheng/p/4961281.html