Minimal cut tree - Different minimum cut CQOI2016

Minimum cut tree

Try to cut the minimum fast between two points of FIG.

Divide and Conquer established:

  1. Optionally two interval \ (X, Y \) , minimum cut running, even edge \ ((x, y, cut_ {x, y}) \)
  2. According to this minimum cut, the point cut into two parts, recursive processing
  3. A new tree, a path is the minimum of two points on their minimal undercut on the original

Time complexity \ (O (the n-^ 3M) \) , but the network card is full flow is difficult

Correctness proof


\(N850M8500\)

Minimal cut tree board questions

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f==1?x:-x;
}
const int N=852,M=17004,inf=0x3f3f3f3f;
int n,m,p[N],p1[N];
set<int>s;
inline void add(int u,int v,int w){
	s.insert(w);
}
namespace gragh{
	struct edge{
		int v,f,yf,nxt;
	}e[M];
	int first[N],cnt=1,cur[N],s,t,cn=0,vis[N],dep[N];
	inline void add(int u,int v,int w){
		e[++cnt]=(edge){v,w,w,first[u]};first[u]=cnt;
		e[++cnt]=(edge){u,w,w,first[v]};first[v]=cnt;
	}
	inline bool bfs(){
		static queue<int>q;
		while(!q.empty())q.pop();
		memset(dep,-1,sizeof(dep));
		dep[s]=1;q.push(s);
		while(!q.empty()){
			int x=q.front();q.pop();
			for(int i=first[x],v;i;i=e[i].nxt){
				v=e[i].v;
				if(e[i].f&&dep[v]==-1){
					dep[v]=dep[x]+1;
					if(v==t)return 1;
					q.push(v);
				}
			}
		} 
		return 0;
	}
	int dfs(int x,int f){
		if(x==t||!f)return f;
		int used=0;
		for(int &i=cur[x],v,w;i;i=e[i].nxt){
			v=e[i].v;
			if(!e[i].f||dep[v]!=dep[x]+1)continue;
			w=dfs(v,min(f,e[i].f));
			if(!w)continue;
			e[i].f-=w;e[i^1].f+=w;
			f-=w;used+=w;
			if(!f)break;
		}
		return used;
	}
	inline int dinic(int u,int v){
		s=u;t=v;
		for(int i=2;i<=cnt;i++)e[i].f=e[i].yf;
		int flow=0;
		while(bfs()){
			memcpy(cur,first,sizeof(first));
			flow+=dfs(s,inf);
		}
		return flow;
	}
	void dfs(int x){
		vis[x]=cn;
		for(int i=first[x],v;i;i=e[i].nxt){
			v=e[i].v;
			if(e[i].f&&vis[v]!=cn)dfs(v);
		}
	}
	void build(int l,int r){
		if(l>=r)return;
		int x=p[l],y=p[l+1],ll=l,rr=r;
		int cut=dinic(x,y);
		cn++;dfs(x);
		for(int i=l;i<=r;i++)
			if(vis[p[i]]==cn)p1[ll++]=p[i];
			else p1[rr--]=p[i];
		for(int i=l;i<=r;i++)p[i]=p1[i];
		::add(x,y,cut);
		build(l,ll-1);build(rr+1,r);
	}
}
int main(){
	n=read();m=read();
	for(int i=1,u,v,w;i<=m;i++){
		u=read();v=read();w=read();
		gragh::add(u,v,w);
	} 
	for(int i=1;i<=n;i++)p[i]=i;
	gragh::build(1,n);
	cout<<s.size(); 
	return (0-0);
}

Guess you like

Origin www.cnblogs.com/aurora2004/p/12567811.html
cut