标签:
题意:K个产奶机,C头奶牛,每个产奶机最多可供M头奶牛使用;并告诉了产奶机、奶牛之间的两两距离Dij(0<=i,j < K+c)。
问题:如何安排使得在任何一头奶牛都有自己产奶机的条件下,奶牛到产奶机的最远距离最短?最短是多少?
先floyd求得两两之间最小距离,然后二分寻找答案
邻接链表的方法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 250
const int INF = 0x3f3f3f3f;
using namespace std;
struct node{
int to, cap, next;
}edge[N*N];
int K, c, m, a[N][N], st, en, n, cnt;
int first[N], level[N], q[N];
int cap[N][N];
void read(int u, int v, int c){
edge[cnt].cap = c;
edge[cnt].next = first[u];
edge[cnt].to = v;
first[u] = cnt++;
edge[cnt].cap = 0;
edge[cnt].next = first[v];
edge[cnt].to = u;
first[v] = cnt++;
}
void init(int dis){
cnt = 0;
memset(first, -1, sizeof(first));
n = K+c;
st = 0;
en = n+1;
for (int i = 1; i <= K; i++){
read(0, i, m);
}
for (int i = K+1; i <= n; i++){
read(i, en, 1);
}
for (int i = 1; i <= K; i++){
for (int j = K+1; j <= n; j++){
if (a[i][j] <= dis){
read(i, j, 1);
}
}
}
}
bool bfs(int s, int t){
memset(level, 0, sizeof(level));
level[s] = 1;
int rear = 0, front = 0;
q[front++] = s;
while(rear < front){
int x = q[rear++];
if (x == t) return true;
for (int e = first[x]; e != -1; e = edge[e].next){
int v = edge[e].to;
int f = edge[e].cap;
if (!level[v] && f){
level[v] = level[x]+1;
q[front++] = v;
}
}
}
return false;
}
int dfs(int u, int maxf, int t){
if (u == t) return maxf;
int ret = 0;
for (int e = first[u]; e != -1; e = edge[e].next){
int v = edge[e].to;
int f = edge[e].cap;
if (level[u]+1 == level[v] && f){
int Min = min(maxf-ret, f);
f = dfs(v, Min, t);
edge[e].cap -= f;
edge[e^1].cap += f;
ret += f;
if (ret == maxf) return ret;
}
}
return ret;
}
int dinic(int s, int t){
int ans = 0;
while(bfs(s, t))
ans += dfs(s, INF, t);
return ans;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1.txt", "r", stdin);
#endif
int i, j, k;
while(~scanf("%d%d%d", &K, &c, &m)){
for (i = 1; i <= K+c; i++){
for (j = 1; j <= K+c; j++){
scanf("%d", &a[i][j]);
if(a[i][j] == 0) a[i][j] = INF;
}
}
for (k = 1; k <= K+c; k++){
for (i = 1; i <= K+c; i++){
for (j = 1; j <= K+c; j++){
a[i][j] = min(a[i][j], a[i][k]+a[k][j]);
}
}
}
int ans = 1, low = 1, high = INF;
while(low <= high){
int mid = (low+high)>>1;
init(mid);
if (dinic(st, en) == c){
ans = mid;
high = mid-1;
}else{
low = mid+1;
}
}
printf("%d\n", ans);
}
return 0;
}
邻接矩阵做法,比邻接表略慢
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 250
const int INF = 0x3f3f3f3f;
using namespace std;
int K, c, m, a[N][N], st, en, n;
int first[N], level[N], q[N];
int cap[N][N];
void Init(int dis){
memset(cap, 0, sizeof(cap));
n = K+c;
st = 0;
en = n+1;
for (int i = 1; i <= K; i++){
cap[0][i] = m;
}
for (int i = K+1; i <= n; i++){
cap[i][en] = 1;
}
for (int i = 1; i <= K; i++){
for (int j = K+1; j <= n; j++){
if (a[i][j] <= dis)
cap[i][j] = 1;
}
}
}
bool bfs(int s, int t){
memset(level, 0, sizeof(level));
level[st] = 1;
int rear = 0, front = 0;
q[front++] = st;
while(rear < front){
int v = q[rear++];
if (v == en) return true;
for (int i = 0; i <= K+c+1; i++){
if (!level[i] && cap[v][i]){
level[i] = level[v] + 1;
q[front++] = i;
}
}
}
return false;
}
int dfs(int u, int maxf, int t){
if (u == t) return maxf;
int ret = 0, f;
for (int i = 1; i <= K+c+1; i++){
if (level[u] + 1 == level[i] && cap[u][i]){
f = dfs(i, min(cap[u][i], maxf-ret), t);
cap[u][i] -= f;
cap[i][u] += f;
ret += f;
if (ret == maxf) return ret;
}
}
return ret;
}
int dinic(int s, int t){
int ans = 0;
while(bfs(s, t))
ans += dfs(s, INF, t);
return ans;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1.txt", "r", stdin);
#endif
int i, j, k;
while(~scanf("%d%d%d", &K, &c, &m)){
for (i = 1; i <= K+c; i++){
for (j = 1; j <= K+c; j++){
scanf("%d", &a[i][j]);
if(a[i][j] == 0) a[i][j] = INF;
}
}
for (k = 1; k <= K+c; k++){
for (i = 1; i <= K+c; i++){
for (j = 1; j <= K+c; j++){
a[i][j] = min(a[i][j], a[i][k]+a[k][j]);
}
}
}
int ans = 1, low = 1, high = INF;
while(low <= high){
int mid = (low+high)>>1;
Init(mid);
if (dinic(st, en) == c){
ans = mid;
high = mid-1;
}else{
low = mid+1;
}
}
printf("%d\n", ans);
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/qq_21120027/article/details/51332651