标签:
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头奶牛,每个产奶机最多可供M头奶牛使用;并告诉了产奶机、奶牛之间的两两距离Dij(0<=i,j<K+C)。
问题:如何安排使得在任何一头奶牛都有自己产奶机的条件下,奶牛到产奶机的最远距离最短?最短是多少?
解:问最远距离最小是肯定是二分查找啦,二分距离,二分图多重匹配判断能否满流;
使用二分图多重匹配+二分方式
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
using namespace std;
const int maxn=300,inf=0x3f3f3f3f,M=300,N=300;
int mp[maxn][maxn],map[maxn][maxn];
int vlink[M],link[M][N];
bool vis[M];
int k,c,w;
int path(int s)
{
for(int i=0;i<k;i++)///挤奶器集合
{
if(map[s][i] && !vis[i])
{
vis[i]=true;
if(vlink[i]<w)///机器可用上限
{
link[i][vlink[i]++]=s;
return 1;
}
for(int j=0;j<vlink[i];j++)
{
if(path(link[i][j]))
{
link[i][j]=s;
return 1;
}
}
}
}
return 0;
}
bool max_match()
{
int ans=0;
memset(vlink,0,sizeof(vlink));
for(int i=0;i<c;i++)///奶牛集合
{
memset(vis,false,sizeof(vis));
if(!path(i))
return false;
}
return true ;///所有奶牛都有一个挤奶器返回真
}
int main()
{
while(~scanf("%d%d%d",&k,&c,&w))
{
for(int i=0;i<c+k;i++)
{
for(int j=0;j<k+c;j++)
{
scanf("%d",&mp[i][j]);
if(mp[i][j]==0)///这里一定要修改,不然会影响floyd算法,
mp[i][j]=inf;
}
}
///floyd必须求
for(int i=0;i<k+c;i++)
{
for(int j=0;j<k+c;j++)
{
for(int l=0;l<k+c;l++)
{
if(mp[j][l]>mp[j][i]+mp[i][l])
mp[j][l]=mp[j][i]+mp[i][l];
}
}
}
int l=0,r=inf,mid;
while(l<r)
{
mid=(l+r)/2;
memset(map,0,sizeof(map));
for(int i=k;i<c+k;i++)///奶牛->机器
{
for(int j=0;j<k;j++)
{
if(mp[i][j]<=mid)///二分查找最短距离
map[i-k][j]=1;
}
}
if(max_match())///二分图多重匹配,奶牛都有机器用时减小上线
r=mid;
else
l=mid+1;
}
cout<<r<<endl;
}
return 0;
}
网络流+二分(两种方式大同小异)
题目描述:
农场主John将他的K(1≤K≤30)个挤奶器运到牧场,在那里有C(1≤C≤200)头奶牛,在奶
牛和挤奶器之间有一组不同长度的路。K个挤奶器的位置用1~K的编号标明,奶牛的位置用K+1~
K+C的编号标明。
每台挤奶器每天最多能为M(1≤M≤15)头奶牛挤奶。
编写程序,寻找一个方案,安排每头奶牛到某个挤奶器挤奶,并使得C头奶牛需要走的所有
路程中的最大路程最小。每个测试数据中至少有一个安排方案。每条奶牛到挤奶器有多条路。
// 本题的求解算法:先用Floyd算法求出能达到的任意两点之间的最短路径,然后用Dinic算法
// 求最大流;搜索最大距离的最小值采用二分法进行。
// 建图问题 : 给个源点 s 。源点到奶牛的流量为1 如果奶牛到达挤奶器距离在max_min范围内 那没就然 该奶牛到该挤奶器的流量为1
// 再给个汇点 那么挤奶器到汇点的流量就是M 正好符合限制
/// 然后二分查找 max_min就可以了
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <string.h>
using namespace std;
#define MOD 1000000007
#define INF 1000000000
#define maxn 310
#define maxm 48010
#define LL __int64//long long
int M,K,C,N;
int cap[maxn][maxn],flow[maxn][maxn];
int dis[maxn][maxn];//,bl[1100];
void build(int max_min){ // 建图
int i,j;
memset(cap,0,sizeof(cap));
memset(flow,0,sizeof(flow));
for(i=1;i<=K;i++) cap[i][N+1]=M;
for(i=K+1;i<=N;i++) cap[0][i]=1;
for(i=K+1;i<=N;i++)
for(j=1;j<=K;j++)
if(dis[i][j]<=max_min) cap[i][j]=1;
}
int level[maxn];
bool BFS(int s,int t){
memset(level,0,sizeof(level));
queue<int> Q;
int u;
int i;
Q.push(s);
level[s]=1;
while(!Q.empty()){
u=Q.front();
Q.pop();
if(u==t) return true;
for(i=1;i<=t;i++)
if(!level[i]&&cap[u][i]>flow[u][i])
{
level[i]=level[u]+1;
Q.push(i);
}
}
return false;
}
int dfs(int u,int maxf,int t){
if(u==t||maxf==0) return maxf;
int ret=0,f,i;
for(i=1;i<=t;i++)
if(cap[u][i]>flow[u][i]&&level[u]+1==level[i]){
f= dfs(i,min(maxf,cap[u][i]-flow[u][i]),t);
flow[u][i]+=f;
flow[i][u]-=f;
maxf-=f;
ret+=f;
if(maxf==0) break;
}
return ret;
}
int Dinic(int s,int t){
int flow=0;
while(BFS(s,t)){
flow+=dfs(s,INF,t);
}
return flow;
}
void init(){
// memset(cap,0,sizeof(cap));
// memset(flow,0,sizeof(flow));
}
int main(){
int i,j,k;
while(scanf("%d %d %d",&K,&C,&M)!=EOF){
N=K+C;
for(i=1;i<=N;i++)
for(j=1;j<=N;j++){
scanf("%d",&dis[i][j]);
if(dis[i][j]==0) dis[i][j]=INF;
}
for(k=1;k<=N;k++)
for(i=1;i<=N;i++)
for(j=1;j<=N;j++)
if(dis[i][j]>dis[i][k]+dis[k][j])
dis[i][j]=dis[i][k]+dis[k][j];
/* for(i=0;i<=N+1;i++,printf("\n"))
for(k=0;k<=N+1;k++)
printf("%d ",cap[i][k]);*/
int L=0,R=100000,mid;
int tp;
while(L<R){// 二分枚举 max_min
mid=(L+R)>>1;
build(mid);
tp=Dinic(0,N+1);
if(tp>=C) R=mid;
else L=mid+1;
}
printf("%d\n",R);
}
return 0;
}
Optimal Milking(二分图多重匹配+二分)(网络流)
标签:
原文地址:http://blog.csdn.net/u014665013/article/details/51345857