Optimal Milking
floyd+多重匹配+二分
先使用floyd求得最短距离
我们二分答案,然后跑多重匹配就好了。
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int max_n = 300;
const int max_m = 1e5;
const int inf = 1e9;
int k,c,m;
int g[max_n][max_n];
struct edge{
int to,next;
}E[max_m<<1];
int head[max_n];
int cnt=1;
void add(int from,int to){
E[cnt].to=to;
E[cnt].next=head[from];
head[from]=cnt++;
}
bool vis[max_n];
vector<int> match[max_n];
bool matchpath(int u,int mid){
for (int i=1;i<=k;++i){
if (!vis[i]&&g[u][i]<=mid){
vis[i]=1;
if (match[i].size()<m){
match[i].push_back(u);
return true;
}
else {
for (int j=0;j<match[i].size();++j){
if (matchpath(match[i][j],mid)){
match[i][j]=u;
return true;
}
}
}
}
}return false;
}
int Hun(int mid){
int ans=0;
for (int i=0;i<=c+k;++i)match[i].clear();
for (int i=k+1;i<=c+k;++i){
fill(vis,vis+k+1,0);
if (matchpath(i,mid))
++ans;
}return ans;
}
bool check(int mid){
return Hun(mid)==c;
}
int binary(){
int lft = 0;int rgt=inf;
while (lft<rgt){
int mid = (lft+rgt)>>1;
if (check(mid))rgt=mid;
else lft=mid+1;
}return rgt;
}
int main(){
scanf("%d %d %d",&k,&c,&m);
for (int i=1;i<=k+c;++i){
for (int j=1;j<=k+c;++j){
scanf("%d",&g[i][j]);
if(g[i][j]==0)g[i][j]=inf;
}
}
for (int K=1;K<=k+c;++K)
for (int i=1;i<=k+c;++i)
for (int j=1;j<=k+c;++j)
g[i][j]=min(g[i][j],g[i][K]+g[K][j]);
printf("%d\n",binary());
}注意了,上面的代码中inf==1e9而不是2e9这是因为,如果是2e9的话,在弗洛伊德的处理时将会爆int然后给我们一个负数,这是很糟糕的。
kuangbin题单刷题详解(匹配问题) 文章被收录于专栏
题单:https://vjudge.net/article/371