Title
Portal POJ 3686
answer
Refer to the white book solution. Considering only one factory, according to Process toys sequentially and observe the minimum total time
Deformed
It can be seen that under different processing orders, each needs to spend times to times the time. Each processing order and the factory's two-tuples correspond to a collection of toys, and the minimum cost flow is sufficient.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define abs(x) ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define delta 0.85
#define eps 1e-5
#define PI 3.14159265358979323846
using namespace std;
#define MAX_V 2555
struct edge{
int to, cap, cost, rev;
edge(int to, int cap, int cost, int rev):to(to), cap(cap), cost(cost), rev(rev){}
};
int V;
vector<edge> G[MAX_V];
int h[MAX_V], dist[MAX_V];
int prevv[MAX_V], preve[MAX_V];
void add_edge(int from, int to, int cap, int cost){
G[from].push_back(edge(to, cap, cost, G[to].size()));
G[to].push_back(edge(from, 0, -cost, G[from].size() - 1));
}
int min_cost_flow(int s, int t, int f){
int res = 0;
memset(h, 0, sizeof(h));
while(f > 0){
// Dijkstra
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > que;
memset(dist, 0x3f, sizeof(dist));
dist[s] = 0;
que.push(pair<int, int>(0, s));
while(!que.empty()){
pair<int, int> p = que.top(); que.pop();
int v = p.second;
if(dist[v] < p.first) continue;
for(int i = 0; i < G[v].size(); i++){
edge &e = G[v][i];
int d2 = dist[v] + e.cost + h[v] - h[e.to];
if(e.cap > 0 && d2 < dist[e.to]){
dist[e.to] = d2;
prevv[e.to] = v;
preve[e.to] = i;
que.push(pair<int, int>(dist[e.to], e.to));
}
}
}
if(dist[t] == INF){
return -1;
}
for(int v = 0; v < V; v++) h[v] += dist[v];
int d = f;
for(int v = t; v != s; v = prevv[v]){
d = min(d, G[prevv[v]][preve[v]].cap);
}
f -= d;
res += d * h[t];
for(int v = t; v != s; v = prevv[v]){
edge &e = G[prevv[v]][preve[v]];
e.cap -= d;
G[v][e.rev].cap += d;
}
}
return res;
}
#define MAX_N 50
#define MAX_M 50
int N, M;
int Z[MAX_N][MAX_M];
void solve(){
int s = N + M * N, t = s + 1;
V = t + 1;
// 清空邻接表元素
for(int v = 0; v < V; v++) G[v].clear();
for(int i = 0; i < N; i++) add_edge(s, i, 1, 0);
// 对每个加工次序和工厂二元组连边
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
add_edge(N + j * M + i, t, 1, 0);
for(int k = 0; k < N; k++){
add_edge(k, N + j * M + i, 1, Z[k][i] * (j + 1));
}
}
}
printf("%.6f\n", (double)min_cost_flow(s, t, N) / N);
}
int main(){
int t;
scanf("%d", &t);
while(t--){
scanf("%d%d", &N, &M);
for(int i = 0; i < N; i++){
for(int j = 0; j < M; j++){
scanf("%d", &Z[i][j]);
}
}
solve();
}
return 0;
}