Learning
多路增广费用流
好吧,只有我觉得这玩意儿好像就是一个spfa标号的dicnic吗
参考dicnic,每次把bfs改成spfa,然后依据\(d_u \leqslant d_c + w(u,v)\)分层就可以了。。。
代码
/*
xsy2692
*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int N = 100 + 10;
const int maxn = 500 + 10;
const int INF = 0x3f3f3f3f;
const int Node = 10010;
const int E = 200000;
inline int rd()
{
int x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
return x;
}
int R, C, n, A, B, xx[8], yy[8], Ans = 0, S, T;
char s[N][N];
int h[Node], ecnt;
struct enode{
int v, n, w, c, op;
enode() {}
enode(int _v, int _n, int _w, int _c, int _op):v(_v), n(_n), w(_w), c(_c), op(_op) {}
}e[E << 1];
inline void addedge(int u, int v, int w, int c) {
// cout << u << ' ' << v << ' ' << ((c >= INF) ? (-1) : (c)) << endl;
ecnt ++; e[ecnt] = enode(v,h[u],w,c,ecnt + 1); h[u] = ecnt;
ecnt ++; e[ecnt] = enode(u,h[v],0,- c,ecnt - 1); h[v] = ecnt;
}
int dist[Node], p[Node], flow = 0;
bool inq[Node];
int q[E];
inline int spfa() {
int head, tail;
head = tail = 1;
memset(dist,0x3f,sizeof(dist));
memset(inq,false,sizeof(inq));
q[tail] = S; inq[S] = true;
dist[S] = 0; p[S] = -1;
while(head <= tail) {
int u = q[head]; head ++;
for(int i = h[u];~ i;i = e[i].n) {
int v = e[i].v;
if(e[i].w > 0 && dist[v] > dist[u] + e[i].c) {
p[v] = e[i].op;
dist[v] = dist[u] + e[i].c;
if(!inq[v]) {
inq[v] = true;
q[++ tail] = v;
}
}
}
inq[u] = false;
}
if(dist[T] >= INF) return 0;
return 1;
}
int cur[maxn];
int dfs(int u, int c) {
if(u == T || c == 0) return c;
inq[u] = 1;
int tmp = 0;
for(int i = cur[u];~ i;i = e[i].n) {
cur[u] = i;
int v = e[i].v;
if(inq[v]) continue;
if(dist[v] == dist[u] + e[i].c && e[i].w > 0) {
int x = dfs(v,min(c,e[i].w));
if(x) {
e[i].w -= x; e[e[i].op].w += x;
tmp += x; c -= x;
Ans += x * e[i].c;
if(!c) break;
}
}
}
return tmp;
}
int main() {
// scanf("%d%d%d%d%d", &R, &C, &n, &A, &B);
R = rd(); C = rd(); n = rd(); A = rd(); B = rd();
memset(h,-1,sizeof(h));
ecnt = 0;
xx[0] = A; yy[0] = B;
xx[1] = A; yy[1] = - B;
xx[2] = - A; yy[2] = B;
xx[3] = - A; yy[3] = - B;
xx[4] = B; yy[4] = A;
xx[5] = B; yy[5] = - A;
xx[6] = - B; yy[6] = A;
xx[7] = - B; yy[7] = - A;
for(int i = 1;i <= R;i ++) {
scanf("%s", s[i] + 1);
}
S = 0; T = R * C + 1;
for(int i = 1;i <= n;i ++) {
int x, y;
// scanf("%d%d", &x, &y);
x = rd(); y = rd();
addedge(S,(x - 1) * C + y,1,0);
}
for(int i = 1;i <= n;i ++) {
int x, y;
// scanf("%d%d", &x, &y);
x = rd(); y = rd();
addedge((x - 1) * C + y,T,1,0);
}
for(int i = 1;i <= R;i ++) {
for(int j = 1;j <= C;j ++) {
if(s[i][j] == '*') continue;
int id = (i - 1) * C + j;
for(int k = 0;k < 8;k ++) {
int dx = i + xx[k];
int dy = j + yy[k];
if(dx < 1 || dy < 1 || dx > R || dy > C || s[dx][dy] == '*') continue;
addedge(id,(dx - 1) * C + dy,INF,1);
}
}
}
Ans = 0;
while(spfa()) {
for(int i = S;i <= T;i ++) cur[i] = h[i];
memset(inq,0,sizeof(inq));
int x = dfs(S,INF);
if(x == 0) break;
flow += x;
}
if(flow != n) Ans = -1;
printf("%d\n", Ans);
return 0;
}
什么你问我复杂度?O(松)