标签:
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