标签:
| Time Limit: 2000MS | Memory Limit: 30000K | |
| Total Submissions: 14040 | Accepted: 5065 | |
| Case Time Limit: 1000MS | ||
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个挤奶机位置用编号1到k表示,奶牛位置用k+1到k+c编号来表示。输入是一个矩阵的形式,对角线表示与自身的位置距离为0,其他为0的位置表示没有边相互连接。问怎么安排每个奶牛到某个挤奶器挤奶,使得c头奶牛需要走的所有路程中最大路程最小。
分析:先用floyd算法求出任意两点之间的最短路,然后在用Dinic求出最大流;在搜索最大距离确定最小值时使用二分法。
#include <iostream>
#include <stdio.h>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF 9999999
#define N 333
using namespace std;
int k,m,c;
int n;
int dis[N][N];//记录两点之间的最短路径
int mp[N][N];//容量网络
int qu[N*100];
int vis[N];//标记数组
int sign[N][N];//层次网络
void build_map(int x)
{
memset(mp,0,sizeof mp);
for(int i=k+1;i<=n;i++) mp[0][i]=1;
for(int i=1;i<=k;i++) mp[i][n+1]=m;
for(int i=k+1;i<=n;i++)
for(int j=1;j<=k;j++)
{
if(dis[i][j]<=x) mp[i][j]=1;
}
}
int bfs()//构建层次网络
{
memset(vis,0,sizeof vis);
memset(sign,0,sizeof sign);
int qs=0,qe=1;
vis[0]=1;
qu[0]=0;
while(qs<qe)
{
int v=qu[qs++];
for(int i=0;i<=n+1;i++)
{
if(vis[i]==0 && mp[v][i])
{
vis[i]=1;
qu[qe++]=i;
sign[v][i]=1;
}
}
}
if(vis[n+1]) return 1;
else return 0;
}
int dfs(int v,int sum)//dfs寻找增广路
{
if(v==n+1) return sum;
int s=sum;
int t;
for(int i=0;i<=n+1;i++)
{
if(sign[v][i])
{
t=dfs(i,min(sum,mp[v][i]));
mp[v][i]-=t;
mp[i][v]+=t;
sum-=t;
}
}
return s-sum;
}
int main()
{
while(~scanf("%d%d%d",&k,&c,&m))
{
n=k+c;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&dis[i][j]);
if(dis[i][j]==0) dis[i][j]=INF;
}
for(int t=1;t<=n;t++)//floyd求解最短路
for(int i=1;i<=n;i++)
{
if(dis[i][t]!=INF)
for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][t]+dis[t][j]);
}
int le=0,ri=10009;
int ans;
while(le<ri)//二分找出最小的最大值
{
int mid=(le+ri)/2;
ans=0;
build_map(mid);//Dinic算法求最大流 while(bfs()) ans+=dfs(0,INF);
if(ans>=c) ri=mid;
else le=mid+1;
}
printf("%d\n",ri);//满足条件的最小的mid用于更新ri
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/wust_zjx/article/details/47706081