码迷,mamicode.com
首页 > 其他好文 > 详细

「一些知识点」

时间:2019-12-10 12:52:53      阅读:85      评论:0      收藏:0      [点我收藏+]

标签:flow   map   pen   style   最小   eve   event   分治   spl   

最小割树

利用一张图的不同割最多只有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\n",ans);
    return 0;
}
View Code

 

「一些知识点」

标签:flow   map   pen   style   最小   eve   event   分治   spl   

原文地址:https://www.cnblogs.com/hzoi2018-xuefeng/p/12015697.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!