Time Limit: 2000MS | Memory Limit: 30000K | |
Total Submissions: 3639 | Accepted: 1458 | |
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
Source
二分图的多重匹配问题,可以先用Floyd算法计算出每两点之间的最短距离,然后找出这些距离中的最大值也就是那条最长路径high,在区间[0,high]中用二分法不断二分得到mid,根据mid来建立二分图,因为这里假设mid是最长路径的最小值,所以当用Floyd算大求解出来的d[i][j]<=mid时,就可以建立一条边,然后根据建立起来的二分图,判断其是否能满足多重匹配.
#include<stdio.h>
#include<string.h>
const int INF=1<<25-1;
int mat[250][250];
bool map[205][35];
int link[35][20];
bool usedif[35];
int k,c,m,high;
void floyed()
{
for(int t=1; t<=k+c; t++)
for(int i=1; i<=k+c; i++)
for(int j=1; j<=k+c; j++)
if(mat[i][t]+mat[t][j]<mat[i][j]) mat[i][j]=mat[i][t]+mat[t][j];
}
bool can(int t)
{
for(int i=1; i<=k; i++)
{
if(usedif[i]==0&&map[t][i])
{
usedif[i]=1;
if(link[i][0]<m)
{
link[i][++link[i][0]]=t;
return true;
}
else
{
for(int j=1; j<=link[i][0]; j++)
if(can(link[i][j]))
{
link[i][j]=t;
return true;
}
}
}
}
return false;
}
bool check(int limit)
{
memset(map,false,sizeof(map));
for(int i=1; i<=k; i++) link[i][0]=0;
for(int i=1; i<=k; i++)
for(int j=k+1; j<=k+c; j++)
if(mat[i][j]<=limit) map[j-k][i]=true;
for(int i=1; i<=c; i++)
{
memset(usedif,0,sizeof(usedif));
if(!can(i)) return false;
}
return true;
}
int find()
{
int high=-1,low=0;
for(int i=1; i<=k+c; i++)
for(int j=1; j<=k+c; j++)
if(mat[i][j]!=INF&&mat[i][j]>high) high=mat[i][j];
while(low<high)
{
int mid=(low+high)>>1;
if(check(mid)) high=mid;
else low=mid+1;
}
return low;
}
int main()
{
while(scanf("%d%d%d",&k,&c,&m)!=EOF)
{
for(int i=1; i<=k+c; i++)
for(int j=1; j<=k+c; j++)
{
scanf("%d",&mat[i][j]);
if(mat[i][j]==0) mat[i][j]=INF;
}
floyed();
printf("%d/n",find());
}
return 0;
}