「一些知识点」
Posted hzoi2018-xuefeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「一些知识点」相关的知识,希望对你有一定的参考价值。
最小割树
利用一张图的不同割最多只有n-1种(我不会证)
利用分治的做法,在l,r区间任意选取两点进行全局最小割,然后把l,r区间分成S,T两个区域(以割边为界限),分别进行递归,递归前要把流量复原保证每次进行的都是全局的最小割。
#include<bits/stdc++.h> #define N 855 #define M 17005 #define inf 0x3f3f3f3f using namespace std; int n,m,S,T,B,ans,head[N],cur[N],dep[N],to[M],nxt[M],flo[M],rec[M],ord[N],tmp[N],vis[N]; map <int,int> Map; inline int rd(){ register int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) f=ch==‘-‘?-1:1,ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-48,ch=getchar(); return x*f; } void lnk(int x,int y,int flow){ to[++B]=y,nxt[B]=head[x],head[x]=B,flo[B]=rec[B]=flow; to[++B]=x,nxt[B]=head[y],head[y]=B,flo[B]=rec[B]=flow; } bool bfs(){ memset(dep,0,sizeof dep); queue <int> q; dep[S]=1; cur[S]=head[S]; q.push(S); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=head[u];i;i=nxt[i]) if(flo[i]&&!dep[to[i]]){ dep[to[i]]=dep[u]+1; cur[to[i]]=head[to[i]]; if(to[i]==T) return 1; q.push(to[i]); } }return 0; } int dfs(int u,int cup){ if(u==T) return cup; int res=cup,v; for(int &i=cur[u];i;i=nxt[i]) if(flo[i]&&dep[to[i]]==dep[u]+1){ v=dfs(to[i],min(res,flo[i])); if(!v) dep[to[i]]=0; else res-=v,flo[i]-=v,flo[i^1]+=v; if(!res) break; }return cup-res; } void Dfs(int x){ vis[x]=1; for(int i=head[x];i;i=nxt[i]) if(flo[i]&&!vis[to[i]]) Dfs(to[i]); } void solve(int l,int r){ if(l>=r) return; S=ord[l]; T=ord[l+1]; int maxflow=0; while(bfs()) maxflow+=dfs(S,inf); if(!Map[maxflow]) ans++; Map[maxflow]=1; memset(vis,0,sizeof vis); Dfs(S); int itl=l-1,itr=r+1; for(int i=l;i<=r;++i) if(vis[ord[i]]) tmp[++itl]=ord[i]; else tmp[--itr]=ord[i]; for(int i=l;i<=r;++i) ord[i]=tmp[i]; memcpy(flo,rec,sizeof flo); solve(l,itl); solve(itr,r); } int main(){ n=rd(); m=rd(); B=1; for(int i=1,x,y,z;i<=m;++i) x=rd(),y=rd(),z=rd(),lnk(x,y,z); for(int i=1;i<=n;++i) ord[i]=i; solve(1,n); printf("%d ",ans); return 0; }
以上是关于「一些知识点」的主要内容,如果未能解决你的问题,请参考以下文章