Summary of minimum tree cutting

P4897 [template] gomory Hu tree

In a graph, for each connected block, a pair of points is selected to run while the minimum cut is made, so that the connected block is split into two halves
In a new graph, each pair of points (u,v)(u,v)(u,v) is connected with an edge between u,vu,vu,v, and the edge weight is their minimum cut
After running n − 1n-1n − 1 minimum cut, all sides are cut out, and in the new graph, it becomes a tree, which is our minimum cut tree
The complexity of tree building o (n3m) O (n3m) O (n3m) O (n3m), but the upper bound is often dissatisfied

The minimum cut of point to u,vu,vu,v becomes the edge with the least edge weight on the path from uuu to vvv
Just use tree section or multiplication query, time complexity O(nlogn)O(nlogn)O(nlogn)

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int Maxn=510,Maxm=6060,inf=0x3f3f3f3f;
struct edge{
	int v,len;
	edge(int x,int y)
	{
		v=x,len=y;
	}
};
int flow[Maxm],nxt[Maxm],to[Maxm];
int head[Maxn],d[Maxn],node[Maxn];
int n,m,q,s,t;
int edgecnt=1;
vector <edge> e[Maxn];
int dis[Maxn][12],f[Maxn][12];
void init()
{
	for(int i=2;i<=edgecnt;i+=2)
	{
		flow[i]+=flow[i^1];
		flow[i^1]=0;
	}
}
inline int read()
{
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return s*w;
}
inline void add(int x,int y,int c)
{
	++edgecnt;
	nxt[edgecnt]=head[x];
	to[edgecnt]=y;
	flow[edgecnt]=c;
	head[x]=edgecnt;
}
bool bfs()
{
	queue <int> q;
	memset(d,0,sizeof(d));
	d[s]=1,q.push(s);
	while(q.size())
	{
		int x=q.front();
		q.pop();
		for(int i=head[x];i;i=nxt[i])
		{
			int y=to[i];
			if(d[y] || !flow[i])continue;
			d[y]=d[x]+1;
			if(y==t)return 1;
			q.push(y);
		}
	}
	return 0;
}
int dinic(int x,int cur)
{
	if(x==t)return cur;
	int ret=cur;
	for(int i=head[x];i && ret;i=nxt[i])
	{
		int y=to[i];
		if(d[y]!=d[x]+1 || !flow[i])continue;
		int tmp=dinic(y,min(ret,flow[i]));
		if(!tmp)d[y]=0;
		flow[i]-=tmp,flow[i^1]+=tmp,ret-=tmp;
	}
	return cur-ret;
}
void build(int l,int r)
{
	if(l==r)return;
	s=node[l],t=node[l+1];
	int val=0,tmp;
	init();
	while(bfs())
	while(tmp=dinic(s,inf))val+=tmp;
	e[s].push_back(edge(t,val));
	e[t].push_back(edge(s,val));
	int a[Maxn],b[Maxn];
	int cnt=0,tot=0;
	for(int i=l;i<=r;++i)
	{
		if(d[node[i]])a[++cnt]=node[i];
		else b[++tot]=node[i];
	}
	for(int i=l;i<l+cnt;++i)
	node[i]=a[i-l+1];
	for(int i=l+cnt;i<=r;++i)
	node[i]=b[i-l-cnt+1];
	build(l,l+cnt-1);
	build(l+cnt,r);
}
void dfs(int x,int fa,int len)
{
	d[x]=d[fa]+1;
	f[x][0]=fa,dis[x][0]=len;
	for(int i=1;i<=10;++i)
	{
		f[x][i]=f[f[x][i-1]][i-1];
		dis[x][i]=min(dis[x][i-1],dis[f[x][i-1]][i-1]);
	}
	for(int i=0;i<e[x].size();++i)
	{
		int y=e[x][i].v;
		if(y==fa)continue;
		dfs(y,x,e[x][i].len);
	}
}
int find(int x,int y)
{
	int ret=inf;
	while(d[x]!=d[y])
	{
		if(d[x]<d[y])swap(x,y);
		for(int i=10;i>=0;--i)
		{
			if(d[f[x][i]]>=d[y])
			{
				ret=min(ret,dis[x][i]);
				x=f[x][i];
			}
		}
	}
	if(x==y)return ret;
	for(int i=10;i>=0;--i)
	{
		if(f[x][i]==f[y][i])continue;
		ret=min(ret,min(dis[x][i],dis[y][i]));
		x=f[x][i],y=f[y][i];
	}
	ret=min(ret,min(dis[x][0],dis[y][0]));
	return ret;
}
int main()
{
//	freopen("in.txt","r",stdin);
	n=read(),m=read();
	for(int i=1;i<=m;++i)
	{
		int x=read(),y=read(),c=read();
		add(x,y,c),add(y,x,0);
		add(y,x,c),add(x,y,0);
	}
	for(int i=1;i<=n;++i)
	node[i]=i;
	build(1,n);
	memset(dis,inf,sizeof(dis));
	memset(d,0,sizeof(d));
	dfs(1,0,0);
	
	q=read();
	while(q--)
	{
		int x=read(),y=read();
		printf("%d\n",find(x,y));
	}
	
	return 0;
}
79 original articles published, praised, 2 visits 2188
Private letter follow

Posted on Tue, 17 Mar 2020 10:46:35 -0400 by wwedude