怎么每天都要被sb错误坑半天..建图的时候竟然忘记了反向边
这道题我们可以考虑把一个地方拆成两个点
, 从源点向
连流量为物品数, 费用0的边,
向汇点连所有物品平均数的边, 然后每个
向对应
连流量
, 费用
的边, 然后对于物品间的运转, 相邻的连流量
, 费用为
的边 一定要建双向边!!!我就是因为这里wa了很多遍, 例如
号点能向
号点运输, 那
号点肯定也可以向
号点运输, 这样子跑最小费用最大流即可
题目链接
#include<bits/stdc++.h>
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
#define go(x, i) for(register int i = head[x]; i; i = nxt[i])
#define rel(x) ((x - 1) % n + 1)
#define inf (0x3f3f3f3f)
using namespace std;
const int maxn = 200 + 10, maxm = 1e5 + 10;
int n, a[maxn], sum, s, t;
namespace Mincost_Maxflow {
int to[maxm << 1], head[maxn], nxt[maxm << 1], w[maxm << 1], v[maxm << 1], e = 1;
int dis[maxn], vis[maxn], cost;
void add(int x, int y, int z, int val) {
to[++ e] = y;
nxt[e]= head[x];
head[x] = e;
w[e] = z;
v[e] = val;
if(z) add(y, x, 0, -val);
}
bool SPFA() {
queue<int> q;
memset(vis, 0, sizeof(vis));
memset(dis, inf, sizeof(dis));
vis[s] = true, dis[s] = 0, q.push(s);
while(!q.empty()) {
int k = q.front(); q.pop();
go(k, i)
if(w[i] && dis[to[i]] > dis[k] + v[i]) {
dis[to[i]] = dis[k] + v[i];
if(!vis[to[i]]) {
vis[to[i]] = true;
q.push(to[i]);
}
}
vis[k] = false;
}
return dis[t] != inf;
}
int dfs(int x, int flow) {
vis[x] = flow;
if(x == t || !flow)
return flow;
int used = 0;
go(x, i)
if(dis[to[i]] == dis[x] + v[i] && !vis[to[i]]) {
int di = dfs(to[i], min(flow, w[i]));
w[i] -= di, w[i ^ 1] += di;
flow -= di, used += di, cost += di * v[i];
if(!flow) break;
}
return used;
}
int dinic() {
int res = 0;
while(SPFA()) {
vis[t] = true;
while(vis[t]) {
memset(vis, 0, sizeof(vis));
res += dfs(s, inf);
}
}
return res;
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("4016.in", "r", stdin);
freopen("4016.out", "w", stdout);
#endif
scanf("%d", &n); s = n << 1 | 1, t = s + 1;
For(i, 1, n) scanf("%d", &a[i]), sum += a[i];
sum /= n;
For(i, 1, n) Mincost_Maxflow::add(s, i, a[i], 0), Mincost_Maxflow::add(i + n, t, sum, 0);
For(i, 1, n) {
Mincost_Maxflow::add(i, i + n, inf, 0);
Mincost_Maxflow::add(rel(i), rel(i + 1), inf, 1);
Mincost_Maxflow::add(rel(i + 1), rel(i), inf, 1);
}
Mincost_Maxflow::dinic(), printf("%d\n", Mincost_Maxflow::cost);
return 0;
}