题目意思是找出奶牛到挤奶机的所有最短距离中的最大值,且挤奶机的容量有限制。这里的做法是寻找二分图的最优多重匹配,要求匹配的权值最小,用floyd+二分枚举最短距离的最大值+最大流验证存在性来做。至于二分图的最优多重匹配的相关知识可以看我的上一个blog,里面有个链接。
以下是代码:
- #include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=300;
const int inf=1<<29;
int min(int a,int b) {return a<b?a:b;}
int s,t;
int map[N][N],flow[N][N],pre[N];
int k,c,m,n; - void init()
{
memset(flow,0,sizeof(flow));
} - void floyd()
{
int i,j,k;
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(i!=j && map[i][k]!=inf && map[k][j]!=inf)
{
if(map[i][j]>map[i][k]+map[k][j])
map[i][j]=map[i][k]+map[k][j];
}
}
} - bool bfs()
{
int i,now;
queue<int> q;
memset(pre,-1,sizeof(pre));
q.push(s);
while(!q.empty())
{
now=q.front();
q.pop();
for(i=0;i<=t;i++)
{
if(pre[i]==-1 && flow[now][i]>0)
{
pre[i]=now;
if(i==t) return true;
q.push(i);
}
}
}
return false;
} - int MaxFlow()
{
int i,j,sum=0;
while(bfs())
{
int min=inf;
for(i=t;i!=s;i=pre[i])
{
if(flow[pre[i]][i]<min)
min=flow[pre[i]][i];
}
for(i=t;i!=s;i=pre[i])
{
flow[pre[i]][i]-=min;
flow[i][pre[i]]+=min;
}
sum+=min;
}
return sum;
} - bool check(int mid)
{
init();
int i,j;
for(i=1;i<=k;i++)
for(j=k+1;j<=n;j++)
if(mid>=map[i][j])
flow[i][j]=1;
for(i=1;i<=k;i++)
flow[s][i]=m;
for(i=k+1;i<=n;i++)
flow[i][t]=1;
return MaxFlow()==c;
} - int main()
{ - scanf("%d%d%d",&k,&c,&m);
int i,j;
n=k+c;
s=0;t=n+1;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
scanf("%d",&map[i][j]);
if(map[i][j]==0 && i!=j)
map[i][j]=inf;
}
floyd();
int max=0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(map[i][j]>max)
max=map[i][j];
}
int low=0,high=max,ans=0;
while(low<=high)
{
int mid=(low+high)/2;
if(check(mid))
{
ans=mid;
high=mid-1;
}
else low=mid+1;
}
printf("%d/n",ans);
return 0;
}