有一些牛,和一些牛奶站,没个牛奶站每天最多收M只牛奶的牛, 怎样安排可以是所有牛到牛奶站的最长路径最短
思路:
路径最短-》最短路
求最大值最小 -》 二分
牛 -》 牛奶站 多值匹配
but这个题二分取值上限要取好, 开始1000 WA了无数次, 然后去了POJ 的 MESSAGE 改成200000就过了
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
#define MAXN 1010
#define INF 0x1f1f1f
int nx, ny, n;
int g[MAXN][MAXN];
int linker[MAXN][MAXN];
bool vis[MAXN];
int limit;
void floyd( )
{
for(int k = 1; k <= n; k++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(g[i][j] > g[i][k] + g[k][j])
g[i][j] = g[i][k] + g[k][j];
}
bool dfs( int u, int dis)
{
for( int v = 1; v <= nx; v ++)
{
if(g[u][v] != INF && g[u][v] <= dis && !vis[v])
{
vis[v] = 1;
if(linker[v][0] < limit)
{
linker[v][++linker[v][0]] = u;
return true;
}
else
{
for( int j = 1; j <= limit; j++)
if(dfs(linker[v][j],dis))
{
linker[v][j] = u;
return true;
}
}
}
}
return false;
}
bool hungary(int dis)
{
for( int i = 1; i <= n; i++)
linker[i][0] = 0;
for( int i = nx+1; i <= n; i++)
{
memset(vis, 0, sizeof(vis));
if(!dfs(i, dis))
return false;
}
return true;
}
void solve( )
{
int l, r;
l = 0, r = 200000;
int mid = 0;
while( l < r)
{
mid = (l + r) >> 1;
if(hungary(mid)) r = mid;
else l = mid + 1;
}
printf("%d\n",r);
}
int main()
{
while(scanf("%d %d %d",&nx, &ny, &limit) != EOF)
{
n = nx + ny;
for( int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
scanf("%d",&g[i][j]);
if(g[i][j] == 0)
g[i][j] = INF;
}
}
floyd();
solve();
}
return 0;
}