[luogu4897]最小割树 Gomory-Hu Tree

luogu P4897

  • 和分治最小割那道题一样,多了一个建图的过程。
  • 建出的图一定是一颗点数为 n n 的树。
  • 查询直接 d f s dfs ,复杂度 5 e 7 5e7 ,开 O 2 O2 过了qwq。其实可以写一下倍增,懒。

Coding

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=501;
const int M=1e4+10;
const int inf=1e9;
int n,m,Q,s,t,tot=1,ans,maxflow,flow,tc,ver[M],Next[M],lin[M],edge[M],yedge[M],d[N],vc[M],nc[M],lc[N],ec[M],v[N];
struct node{
	int id,val;
}a[N];
int read(){
	char ch=getchar();int num=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){num=(num<<1)+(num<<3)+(ch^48);ch=getchar();}
	return num*f;
}
void add(int x,int y,int z){ver[++tot]=y;Next[tot]=lin[x];lin[x]=tot;edge[tot]=z;yedge[tot]=z;}
void addc(int x,int y,int z){vc[++tc]=y;nc[tc]=lc[x];lc[x]=tc;ec[tc]=z;}
bool cmp(node a,node b){return d[a.id]<d[b.id];}
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=lin[x];i;i=Next[i]){
			int y=ver[i];
			if(!d[y]&&edge[i]){
				d[y]=d[x]+1;q.push(y);
				if(y==t) return 1;
			}
		}
	}return 0;
}
int dinic(int x,int flow){
	if(x==t) return flow;
	int rest=flow;
	for(int i=lin[x];i&&rest;i=Next[i]){
		int y=ver[i];
		if(d[y]==d[x]+1&&edge[i]){
			int k=dinic(y,min(edge[i],rest));
			if(!k) d[y]=0;
			rest-=k,edge[i]-=k,edge[i^1]+=k;
			if(!rest) return flow-rest;
		}
	}return flow-rest;
}
void CDQ(int l,int r){
	if(l==r) return;
	s=a[l].id,t=a[r].id;
	maxflow=flow=0;
	for(int i=2;i<=tot;++i) edge[i]=yedge[i];
	while(bfs()){
		while(flow=dinic(s,inf)) maxflow+=flow;
	}
	addc(s,t,maxflow);addc(t,s,maxflow);
	sort(a+l,a+r+1,cmp);
	int mid;
	for(int i=l;i<=r;++i) if(d[a[i].id]>0){mid=i-1;break;}
	CDQ(l,mid);CDQ(mid+1,r);
}
void dfs(int x,int now,int temp){
	v[x]=1;
	if(x==now){
		ans=temp;return;
	}
	for(int i=lc[x];i;i=nc[i]){
		int y=vc[i];
		if(v[y]) continue;
		dfs(y,now,min(temp,ec[i]));
	}
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=m;++i){
		int x=read(),y=read(),z=read();
		add(x,y,z);add(y,x,z);
	}
	for(int i=0;i<=n;++i) a[i].id=i;
	CDQ(0,n);
	Q=read();
	while(Q--){
		int x=read(),y=read();
		ans=1e9;for(int i=0;i<=n;++i) v[i]=0;
		dfs(x,y,1e9);
		printf("%d\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39759315/article/details/88804878