ACM/ICPC 之 Dinic算法(POJ2112)

时间:2023-03-09 16:42:35
ACM/ICPC 之 Dinic算法(POJ2112)

  Optimal Milking

//二分枚举最大距离的最小值+Floyd找到最短路+Dinic算法
//参考图论算法书,并对BFS构建层次网络算法进行改进
//Time:157Ms Memory:652K
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std; #define MAX 250
#define INF 0x3f3f3f3f int K, C, M;
int s, t;
int d[MAX][MAX]; //各点间最短距离
int res[MAX][MAX]; //残留网络
int lev[MAX]; void build_map(int limit)
{
memset(res,0,sizeof(res));
for (int i = K + 1; i <= K + C; i++)
res[s][i] = 1;
for (int i = 1; i <= K; i++)
res[i][t] = M;
for (int i = K + 1; i <= K + C; i++)
for (int j = 1; j <= K; j++)
if (d[i][j] <= limit) res[i][j] = 1;
} bool bfs() //BFS标记层次网络
{
memset(lev, -1, sizeof(lev));
queue<int> q;
q.push(s);
lev[s] = 0;
while (!q.empty()) { //构建层次网络
int cur = q.front();
q.pop();
for(int i = 1; i <= t; i++)
{
if(lev[i] == -1 && res[cur][i]) //未访问且正向有流量
{
q.push(i);
lev[i] = lev[cur] + 1;
}
}
}
return lev[t] != -1;
} int dfs(int v, int alpha) //DFS进行多次增广
{
if(v == t || alpha == 0) return alpha;
int src = alpha; //原可改进量
for(int i = 1; i <= t; i++)
{
if(res[v][i] && lev[i] == lev[v] + 1){ //识别下一层次
int tmp = dfs(i, min(alpha, res[v][i]));
res[v][i] -= tmp;
res[i][v] += tmp;
alpha -= tmp; //可改进量减少
}
}
return src - alpha; //总改进量
} int main()
{
//freopen("in.txt", "r", stdin); scanf("%d%d%d", &K,&C,&M);
s = 0; t = K + C + 1; //源点-汇点
for (int i = 1; i < t; i++)
for (int j = 1; j < t; j++)
{
scanf("%d", &d[i][j]);
if (d[i][j] == 0) d[i][j] = INF;
} for (int k = 1; k < t; k++)
for (int i = 1; i < t; i++)
{
if (d[i][k] != INF) {
for (int j = 1; j < t; j++)
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
} s = 0; t = K + C + 1; //源点 汇点
int l = 0, r = 9000;
while (l < r)
{
int ans = 0; //到达目的地的奶牛数量
int mid = (l + r) / 2;
build_map(mid);
while (bfs())
ans += dfs(0,INF); //第二参数指定该点可改进量
ans == C ? r = mid: l = mid+1;
}
printf("%d\n", r); return 0;
}