BZOJ 4519: [Cqoi2016]不同的最小割

裸的最小割樹(分治最小割是啥,能喫嗎)

簡單的看了一下最小割樹的建樹方法

首先以1爲根建立星型(菊花)

然後對於2到n每個節點:

跑它(S)和它父親(T)的最小割

得出來的最小割即爲樹上該條邊的權值

然後找到比該節點編號大的節點,如果它的父親爲T且它在S集中,那麼把它的父親置爲S

搞下一個節點

複雜度就是最小割*n

然後樹上兩點間路徑的瓶頸即爲兩點間最小割(好像可以查詢的樣子哎)

於是答案就是最小割樹的邊集的值的集合的大小(一口氣說完真爽

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
#define mmt(a,v) memset(a,v,sizeof(a))
#define tra(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
typedef long long ll;
const int inf=1e9;
const int N=850+5;
const int M=8500+5;
struct Edge{int to,next,v,c;}e[M<<1];
int head[N],cnt=1;
void ins(int u,int v,int w){e[++cnt]=(Edge){v,head[u],w,w};head[u]=cnt;}
void insert(int u,int v,int w){ins(u,v,w);ins(v,u,w);}
int d[N];
bool bfs(int s,int t){
    mmt(d,-1);d[s]=0;queue<int>q;q.push(s);
    while(!q.empty()){
        int u=q.front();q.pop();
        tra(i,u)
        if(e[i].v&&d[e[i].to]==-1){
            d[e[i].to]=d[u]+1;
            q.push(e[i].to);
        }
    }
    return d[t]!=-1;
}
int dfs(int u,int f,int t){
    if(u==t)return f;
    int flow=0,w;
    tra(i,u)
    if(e[i].v&&d[e[i].to]==d[u]+1){
        w=dfs(e[i].to,min(e[i].v,f-flow),t);
        e[i].v-=w;e[i^1].v+=w;flow+=w;
        if(flow==f)return f;
    }
    if(!flow)d[u]=-1;
    return flow;
}
int dinic(int s,int t){int ans=0;while(bfs(s,t))ans+=dfs(s,inf,t);return ans;}
bool g[N][N];
int fa[N],vis[N];
set<int>s;
void dfs(int u,int T){
    vis[u]=T;
    tra(i,u)
    if(e[i].v&&vis[e[i].to]!=T)
    dfs(e[i].to,T);
}
void Gomory_Hu_Tree(int n){
    rep(i,2,n)fa[i]=1;
    rep(i,2,n){
        s.insert(dinic(i,fa[i]));
        static int T=0;T++;
        dfs(i,T);
        rep(j,i+1,n)
        if(vis[j]==T&&fa[j]==fa[i])
        fa[j]=i;
        rep(j,2,cnt)e[j].v=e[j].c;
    }
}
int main(){
    //freopen("a.in","r",stdin);
    int n,m;scanf("%d%d",&n,&m);
    while(m--){int u,v,w;scanf("%d%d%d",&u,&v,&w);insert(u,v,w);g[u][v]=g[v][u]=1;}
    Gomory_Hu_Tree(n);
    printf("%d\n",(int)s.size());
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章