最小割树 - CQOI2016不同的最小割
Posted aurora2004
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小割树 - CQOI2016不同的最小割相关的知识,希望对你有一定的参考价值。
最小割树
快速求无向图两点间的最小割
分治建立:
- 区间内任选两点(x,y),跑最小割,连边((x,y,cut_{x,y}))
- 根据此最小割,把点割成两部分,递归处理
- 新建出的树,两点路径上的最小值即为他们在原图上的最小割
时间复杂度(O(n^3m)),但网络流很难卡满
(N850M8500)
最小割树板题
#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);
}
以上是关于最小割树 - CQOI2016不同的最小割的主要内容,如果未能解决你的问题,请参考以下文章