| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
转换为最小费用流RT,每个点拆点建图,每次路径必然经过4N-1次边,故可将每条边cost设置INF-cost(INF=1010),求出最小费用之后,结果为 K * (4N - 1) *INF - min_cost_flow
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <utility>
#include <vector>
using namespace std;
const int MAXN = 5010;
const int INF = 1010;
typedef pair<int, int> Pr;
int inline min(int a, int b) {
return a <= b ? a : b;
}
struct edge {
int to, cap, cost, rev;
};
int N, K, V;
vector<edge> graph[MAXN];
int h[MAXN], dis[MAXN], prevv[MAXN], preve[MAXN];
void add_edge(int from, int to, int cap, int cost) {
graph[from].push_back(edge{to, cap, cost, graph[to].size()});
graph[to].push_back(edge{from, 0, -cost, graph[from].size() - 1});
}
int min_cost_flow(int s, int t, int f) {
int ans = 0;
memset(h, 0, sizeof(h));
while (f > 0) {
priority_queue<Pr, vector<Pr>, greater<Pr> > pq;
fill(dis, dis + V, INF * INF);
dis[s] = 0;
pq.push(Pr(0, s));
while (!pq.empty()) {
Pr cur = pq.top();
pq.pop();
int v = cur.second;
if (dis[v] < cur.first) continue;
for (int i = 0; i < graph[v].size(); ++i) {
edge& e = graph[v][i];
if (e.cap > 0 && dis[e.to] > dis[v] + e.cost + h[v] - h[e.to]) {
dis[e.to] = dis[v] + e.cost + h[v] - h[e.to];
prevv[e.to] = v;
preve[e.to] = i;
pq.push(Pr(dis[e.to], e.to));
}
}
}
if (dis[t] == INF) return -1;
for (int v = 0; v < V; ++v) h[v] += dis[v];
int d = f;
for (int v = t; v != s; v = prevv[v]) d = min(d, graph[prevv[v]][preve[v]].cap);
f -= d;
ans += d * h[t];
for (int v = t; v != s; v = prevv[v]) {
edge& e = graph[prevv[v]][preve[v]];
e.cap -= d;
graph[v][e.rev].cap += d;
}
}
return ans;
}
int main() {
while (scanf("%d%d", &N, &K) != EOF && N) {
V = N * N * 2 + 2;
int s = V - 2, t = V - 1, cost, shift = N * N;
for (int i = 0; i < V; ++i) graph[i].clear();
add_edge(s, 0, K, INF);
add_edge(N * N * 2 - 1, t, K, INF);
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
scanf("%d", &cost);
if (cost != 0) add_edge(i * N + j, shift + i * N + j, 1, INF - cost);
add_edge(i * N + j, shift + i * N + j, K, INF);
if (i + 1 < N) add_edge(shift + i * N + j, (i + 1) * N + j, K, INF);
if (j + 1 < N) add_edge(shift + i * N + j, i * N + j + 1, K, INF);
}
}
printf("%d\n", K * (4 * N - 1) * INF - min_cost_flow(s, t, K));
}
return 0;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator