⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 network.cpp

📁 ACM经典算法ACM经典算法ACM经典算法
💻 CPP
📖 第 1 页 / 共 2 页
字号:
                i = bf[cur[i]].y;
            }
            else {
				if (0 == top) break;
                dep[i] = -1; i = bf[ps[--top]].x;
            }
        }
    }
    return res;
}
/*============================================================*\
 | HLPP最大流 O(V^3)                                          |
 | INIT: network g; g.build(nv, ne);                          |
 | CALL: res = g.maxflow(s, t);                               |
 | 注意: 不要加入指向源点的边, 可能死循环.                    |
\*============================================================*/
#define typef int                   // type of flow
const typef inf = 0x3f3f3f3f;       // max of flow
typef minf(typef a, typef b) { return a < b ? a : b; }

struct edge {
	int u, v; typef cuv, cvu, flow;
	edge (int x=0, int y=0, typef cu=0, typef cv=0, typef f=0)
		: u(x), v(y), cuv(cu), cvu(cv), flow(f) {}
	int other(int p) { return p == u ? v : u; }
	typef cap(int p) {
		return p == u ? cuv-flow : cvu+flow;
	}
	void addflow(int p, typef f) { flow += (p == u ? f : -f); }
};

struct vlist {
	int lv, next[N], idx[2 * N], v;
	void clear(int cv) {
		v = cv; lv = -1;
		memset(idx, -1, sizeof(idx));
	}
	void insert(int n, int h) {
		next[n] = idx[h]; idx[h] = n;
		if (lv < h) lv = h;
	}
	int remove() {
		int r = idx[lv];  idx[lv] = next[idx[lv]];
		while (lv >= 0 && idx[lv] == -1) lv--;
		return r;
	}
	bool empty() { return lv < 0; }
};

struct network {
	vector<edge> eg;
	vector<edge*> net[N];
	vlist list;
	typef e[N];
	int v, s, t, h[N], hn[2 * N], cur[N];
	void push(int);
	void relabel(int);
	void build(int, int);
	typef maxflow(int, int);
};
void network::push(int u) {
	edge* te = net[u][cur[u]];
	typef ex = minf(te->cap(u), e[u]);
	int p = te->other(u);
	if (e[p] == 0 && p != t) list.insert(p, h[p]);
	te->addflow(u, ex); e[u] -= ex; e[p] += ex;
}
void network::relabel(int u) {
	int i, p, mh = 2 * v, oh = h[u];
	for (i = net[u].size()-1; i >= 0; i--) {
		p = net[u][i]->other(u);
		if (net[u][i]->cap(u) != 0 && mh > h[p] + 1)
			mh = h[p] + 1;
	}
	hn[h[u]]--; hn[mh]++; h[u] = mh;
	cur[u] = net[u].size()-1;

	if (hn[oh] != 0 || oh >= v + 1) return;
	for (i = 0; i < v; i++)
		if (h[i] > oh && h[i] <= v && i != s) {
			hn[h[i]]--; hn[v+1]++; h[i] = v + 1;
		}
}
typef network::maxflow(int ss, int tt) {
	s = ss; t = tt;
	int i, p, u;  typef ec;

	for (i = 0; i < v; i++) net[i].clear();
	for (i = eg.size()-1; i >= 0; i--) {
		net[eg[i].u].push_back(&eg[i]);
		net[eg[i].v].push_back(&eg[i]);
	}

	memset(h, 0, sizeof(h)); memset(hn, 0, sizeof(hn));
	memset(e, 0, sizeof(e)); e[s] = inf;
	for (i = 0; i < v; i++) h[i] = v;
	queue<int> q; q.push(t); h[t] = 0;
	while (!q.empty()) {
		p = q.front(); q.pop();
		for (i = net[p].size()-1; i >= 0; i--) {
			u = net[p][i]->other(p); ec = net[p][i]->cap(u);
			if (ec != 0 && h[u] == v && u != s) {
				h[u] = h[p] + 1; q.push(u);
			}
		}
	}
	for (i = 0; i < v; i++) hn[h[i]]++;

	for (i = 0; i < v; i++) cur[i] = net[i].size()-1;
	list.clear(v);
	for (; cur[s] >= 0; cur[s]--) push(s);

	while (!list.empty()) {
		for (u = list.remove(); e[u] > 0; ) {
			if (cur[u] < 0) relabel(u);
			else if (net[u][cur[u]]->cap(u) > 0 &&
				h[u] == h[net[u][cur[u]]->other(u)]+1) push(u);
			else cur[u]--;
		}
	}
	return e[t];
}
void network::build(int n, int m) {
	v = n; eg.clear();
	int a, b, i;  typef l;
	for (i = 0; i < m; i++) {
		cin >> a >> b >> l;
		eg.push_back(edge(a, b, l, 0)); // vertex: 0 ~ n-1
	}
}
/*============================================================*\
 | 最小费用流 O(V * E * f)                                    |
 | INIT: network g; g.build(v, e);                            |
 | CALL: g.mincost(s, t); flow=g.flow; cost=g.cost;           |
 | 注意: SPFA增广, 实际复杂度远远小于O(V * E);                |
\*============================================================*/
#define typef int                    // type of flow
#define typec int                    // type of dis
const typef inff = 0x3f3f3f3f;       // max of flow
const typec infc = 0x3f3f3f3f;       // max of dis
struct network
{
	int nv, ne, pnt[E], nxt[E];
	int vis[N], que[N], head[N], pv[N], pe[N];
	typef flow, cap[E]; typec cost, dis[E], d[N];
	void addedge(int u, int v, typef c, typec w) {
		pnt[ne] =  v; cap[ne] = c;
		dis[ne] = +w; nxt[ne] = head[u]; head[u] = (ne++);
		pnt[ne] =  u; cap[ne] = 0;
		dis[ne] = -w; nxt[ne] = head[v]; head[v] = (ne++);
	}
	int mincost(int src, int sink) {
		int i, k, f, r; typef mxf;
		for (flow = 0, cost = 0; ; ) {
			memset(pv, -1, sizeof(pv));
			memset(vis, 0, sizeof(vis));
			for (i = 0; i < nv; ++i) d[i] = infc;
			d[src] = 0; pv[src] = src; vis[src] = 1;

			for (f = 0, r = 1, que[0] = src; r != f; ) {
				i = que[f++]; vis[i] = 0; if (N == f) f = 0;
				for (k = head[i]; k != -1; k = nxt[k])
					if (cap[k] && dis[k] + d[i] < d[pnt[k]]) {
						d[pnt[k]] = dis[k] + d[i];
						if (0 == vis[pnt[k]]) {
							vis[pnt[k]] = 1; que[r++] = pnt[k];
							if (N == r) r = 0;
						}
						pv[pnt[k]]=i; pe[pnt[k]]=k;
					}
			}
			if (-1 == pv[sink]) break;

			for (k = sink, mxf = inff; k != src; k = pv[k])
				if (cap[pe[k]] < mxf) mxf = cap[pe[k]];
			flow += mxf; cost += d[sink] * mxf;

			for (k = sink; k != src; k = pv[k]) {
				cap[pe[k]] -= mxf; cap[pe[k] ^ 1] += mxf;
			}
		}
		return cost;
	}
	void build(int v, int e) {
		nv = v; ne = 0;
		memset(head, -1, sizeof(head));
		int x, y; typef f; typec w;
		for (int i = 0; i < e; ++i) {
			cin >> x >> y >> f >> w;  // vertex: 0 ~ n-1
			addedge(x, y, f, w);      // add arc (u->v, f, w)
		}
	}
} g;
/*============================================================*\
 | 最小费用流 O(V^2 * f)                                      |
 | INIT: network g; g.build(nv, ne);                          |
 | CALL: g.mincost(s, t); flow=g.flow; cost=g.cost;           |
 | 注意: 网络中弧的cost需为非负. 若存在负权, 进行如下转化:    |
 |  首先如果原图有负环, 则不存在最小费用流. 那么可以用Johnson |
 | 重标号技术把所有边变成正权, 以后每次增广后进行维护, 算法如 |
 | 下:                                                        |
 |  1. 用bellman-ford求s到各点的距离phi[];                    |
 |  2. 以后每求一次最短路, 设s到各点的最短距离为dis[]:        |
 |     for i=1 to v do                                        |
 |       phi[v] += dis[v];                                    |
 | 下面的代码已经做了第二步, 如果原图有负权, 添加第一步即可.  |
\*============================================================*/
#define typef int                    // type of flow
#define typec int                    // type of cost
const typef inff = 0x3f3f3f3f;       // max of flow
const typec infc = 0x3f3f3f3f;       // max of cost

struct edge {
	int u, v; typef cuv, cvu, flow; typec cost;
	edge (int x, int y, typef cu, typef cv, typec cc)
		: u(x), v(y), cuv(cu), cvu(cv), flow(0), cost(cc) {}
	int other(int p) { return p == u ? v : u; }
	typef cap(int p) { return p == u ? cuv-flow : cvu+flow; }
	typec ecost(int p) {
		if (flow == 0) return cost;
		else if(flow > 0) return p == u ? cost : -cost;
		else return p == u ? -cost : cost;
	}
	void addFlow(int p, typef f) { flow += (p == u ? f : -f); }
};

struct network {
	vector<edge> eg;
	vector<edge*> net[N];
	edge *prev[N];
	int v, s, t, pre[N], vis[N];
	typef flow; typec cost, dis[N], phi[N];
	bool dijkstra();
	void build(int nv, int ne);
	typec mincost(int, int);
};
bool network::dijkstra()
{	// 使用O(E * logV)的Dij可降低整体复杂度至 O(E * logV * f)
	int i, j, p, u; typec md, cw;
	for (i = 0; i < v; i++) dis[i] = infc;
	dis[s] = 0; prev[s] = 0; pre[s] = -1;
	memset(vis, 0, v * sizeof(int));
	for (i = 1; i < v; i++) {
		for (md = infc, j = 0; j < v; j++)
			if (!vis[j] && md > dis[j]) { md = dis[j]; u = j; }
		if (md == infc) break;
		for (vis[u] = 1, j = net[u].size()-1; j >= 0; j--) {
			edge *ce = net[u][j];
			if(ce->cap(u) > 0) {
				p = ce->other(u);
				cw = ce->ecost(u) + phi[u] - phi[p];
				// !! assert(cw >= 0);
				if(dis[p] > dis[u]+cw) {
					dis[p] = dis[u] + cw;
					prev[p] = ce;   pre[p] = u;
				}
			}
		}
	}
	return infc != dis[t];
}
typec network::mincost(int ss, int tt) {
	s = ss; t = tt;
	int i, c;  typef ex;

	flow = cost = 0;
	memset(phi, 0, sizeof(phi));
	// !! 若原图含有负消费的边, 在此处运行Bellmanford
	// 将phi[i](0<=i<=n-1)置为mindist(s, i).

	for (i = 0; i < v; i++) net[i].clear();
	for (i = eg.size()-1; i >= 0; i--) {
		net[eg[i].u].push_back(&eg[i]);
		net[eg[i].v].push_back(&eg[i]);
	}

	while(dijkstra()) {
		for (ex = inff, c = t; c != s; c = pre[c])
			if (ex > prev[c]->cap(pre[c]))
				ex = prev[c]->cap(pre[c]);
		for (c = t; c != s; c = pre[c])
			prev[c]->addFlow(pre[c], ex);
		flow += ex; cost += ex * (dis[t] + phi[t]);
		for (i = 0; i < v; i++) phi[i] += dis[i];
	}
	return cost;
}
void network::build(int nv, int ne) {
	eg.clear(); v = nv;
	int x, y; typef f; typec c;
	for (int i = 0; i < ne; ++i) {
		cin >> x >> y >> f >> c;
		eg.push_back(edge(x, y, f, 0, c));
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -