CQOI2016 不同的最小割 (最小割树模板)(等价流树的Gusfield构造算法)

题目

最小割树模板

算法详解及证明见:

2016年国家队候选队员论文
《浅谈无向图最小割问题的一些算法及应用——绍兴一中 王文涛》
3.2节

CODE

#include <bits/stdc++.h>
using namespace std;
template<class T>inline void read(T &x) {
	char ch; while(!isdigit(ch=getchar()));
	for(x=ch-'0';isdigit(ch=getchar());x=x*10+ch-'0');
}
const int MAXN = 855;
const int MAXM = 8505;
const int inf = 1e9;
int n, m, Q;
int info[MAXN], fir[MAXN], to[MAXM<<1], nxt[MAXM<<1], c[MAXM<<1], C[MAXM<<1], cnt;
inline void link(int u, int v, int cc, int rc) {
	to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt; C[cnt] = cc;
	to[++cnt] = u; nxt[cnt] = fir[v]; fir[v] = cnt; C[cnt] = rc;
}
int dis[MAXN];
queue<int>q;
int S, T;
bool bfs() {
	memset(dis, -1, sizeof dis);
	dis[S] = 0; q.push(S);
	while(!q.empty()) {
		int u = q.front(); q.pop();
		for(int i = fir[u], v; i; i = nxt[i])
			if(c[i] && !(~dis[v=to[i]]))
				dis[v] = dis[u] + 1, q.push(v);
	}
	return ~dis[T];
}
bool vis[MAXN];
int aug(int u, int Max) {
	if(u == T) return Max;
	int delta, flow = 0;
	vis[u] = 1;
	for(int v, &i = info[u]; i; i = nxt[i])
		if(c[i] && !vis[v=to[i]] && dis[v] == dis[u]+1 && (delta=aug(v, min(Max-flow, c[i])))) {
			c[i] -= delta; c[i^1] += delta; flow += delta;
			if(flow == Max) break;
		}
	vis[u] = 0;
	return flow;
}
int maxflow(int ss, int tt) {
	S = ss, T = tt;
	int re = 0;
	while(bfs()) memcpy(info, fir, sizeof info), re += aug(S, inf);
	return re;
}
int fa[MAXN], val[MAXN], ans[MAXN][MAXN], seq[MAXN*MAXN], cur;
void dfs(int u) {
	if(vis[u]) return;
	vis[u] = 1;
	for(int i = fir[u]; i; i = nxt[i])
		if(c[i]) dfs(to[i]);
}
vector<pair<int,int> >e[MAXN];
void getans(int u, int ff, int now, int s) {
	ans[s][u] = now;
	for(int i = e[u].size()-1, v; i >= 0; --i)
		if((v=e[u][i].first) != ff)
			getans(v, u, min(now, e[u][i].second), s);
}
int main () {
		read(n), read(m); cnt = 1;
		for(int i = 1, u, v, c; i <= m; ++i) {
			read(u), read(v), read(c);
			link(u, v, c, c);
		}
		fa[1] = 0;
		for(int i = 2; i <= n; ++i) fa[i] = 1;
		for(int i = 2; i <= n; ++i) {
			memcpy(c, C, sizeof c);
			val[i] = maxflow(i, fa[i]);
			dfs(i);
			for(int j = i+1; j <= n; ++j)
				if(vis[j] && fa[i] == fa[j]) fa[j] = i;
			memset(vis, 0, sizeof vis);
		}
		for(int i = 2; i <= n; ++i)
			e[fa[i]].push_back(make_pair(i, val[i])),
			e[i].push_back(make_pair(fa[i], val[i]));
		cur = 0;
		for(int i = 1; i <= n; ++i) {
			getans(i, 0, inf, i);
			for(int j = i+1; j <= n; ++j)
				seq[++cur] = ans[i][j];
		}
		sort(seq + 1, seq + cur + 1);
		cur = unique(seq + 1, seq + cur + 1) - seq - 1;
		printf("%d\n", cur);
}
发布了367 篇原创文章 · 获赞 239 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/Ike940067893/article/details/103326324