zoukankan      html  css  js  c++  java
  • CF343E Pumping Stations(最小割树)

    没学过最小割树的出门左转。

    我们已经知道了两点的最小割就是最小割树上,对应两点之间路径的权值的最小值。
    找到最小割树中权值的最小的边。
    那么一定是先选完一侧的点在选完另一侧的点。
    因为当前边最小,那么左右横跳的贡献最小(比在一侧内跳的贡献小)。
    所以一直递归下去就行了。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N=520;
    const int M=1600;
    const int INF=1e9;
    int cnt=1,head[N];
    struct edge{
        int to,nxt,flow;
    }e[M*4];
    void add_edge(int u,int v,int flow){
        cnt++;
        e[cnt].nxt=head[u];
        e[cnt].to=v;
        e[cnt].flow=flow;
        head[u]=cnt;
    }
    int tcnt=1,thead[N];
    struct EDGE{
        int to,nxt,w,vis;
    }te[N*2];
    void add(int u,int v,int w){
        tcnt++;
        te[tcnt].nxt=thead[u];
        te[tcnt].to=v;
        te[tcnt].w=w;
        thead[u]=tcnt;
    }
    int S,T,dis[N];
    bool bfs(){
        memset(dis,-1,sizeof(dis));
        dis[S]=0;
        queue<int> q;
        q.push(S);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=head[u];i;i=e[i].nxt){
                int v=e[i].to;
                if(dis[v]==-1&&e[i].flow){
                    dis[v]=dis[u]+1;
                    q.push(v);
                }
            }
        }
        if(dis[T]==-1)return false;
        return true;
    }
    int dfs(int u,int f){
        if(u==T||f==0)return f;
        int used=0;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(dis[v]==dis[u]+1&&e[i].flow){
                int w=dfs(v,min(f-used,e[i].flow));
                if(w){
                    e[i].flow-=w;
                    e[i^1].flow+=w;
                    used+=w;
                    if(used==f)return f;
                }
            }
        }
        if(used==0)dis[u]=-1;
        return used;
    }
    int ans;
    void Dinic(){
        for(int i=2;i<=cnt;i+=2)e[i].flow=e[i].flow+e[i^1].flow,e[i^1].flow=0;ans=0;
        while(bfs())ans+=dfs(S,INF);
    }
    int col[N];
    void _dfs(int u,int c){
        col[u]=c;
        for(int i=head[u];i;i=e[i].nxt){
        	int v=e[i].to;
            if(e[i].flow&&col[v]!=c)_dfs(v,c);
        }
    }
    int node[N],tot,c[N];
    void build(int l,int r){
        if(l==r) return ;
        S=node[l],T=node[l+1];
        Dinic();
        _dfs(S,++tot);
        int L=l,R=r;
        for(int i=l;i<=r;i++)
            if(col[node[i]]==tot)c[L++]=node[i];
            else c[R--]=node[i];
        for(int i=l;i<=r;i++)node[i]=c[i];
        add(S,T,ans);add(T,S,ans);
        build(l,L-1);build(R+1,r);
    }
    int read(){
        int sum=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
        return sum*f;
    }
    int n,m;
    int x,y,mn,id,ANS,num,anss[N];
    bool dfs_(int u,int f){
        bool flag=false;
        for(int i=thead[u];i;i=te[i].nxt){
            int v=te[i].to;
            if(v==f||te[i].vis)continue;
            if(te[i].w<mn){x=u,y=v;mn=te[i].w;id=i;}
            dfs_(v,u);
            flag=true;
        }
        return flag;
    }
    void work(int u){
        mn=INF;
        if(!dfs_(u,0)){anss[++num]=u;return;}
        te[id].vis=te[id^1].vis=1;
        ANS+=mn;
        int a=x,b=y;
        work(a);
        work(b);
    }
    int main(){
        n=read();m=read();
        for(int i=1;i<=m;i++){
            int u=read(),v=read(),w=read();
            add_edge(u,v,w);add_edge(v,u,0);
            add_edge(v,u,w);add_edge(u,v,0);
        }
        for(int i=1;i<=n;i++)node[i]=i;
        build(1,n);
        work(1);
        printf("%d
    ",ANS);
        for(int i=1;i<=num;i++)printf("%d ",anss[i]);
        return 0;
    }
    
  • 相关阅读:
    loj#6433. 「PKUSC2018」最大前缀和(状压dp)
    PKUWC2019游记
    10. Regular Expression Matching
    9. Palindrome Number
    8. String to Integer (atoi)
    7. Reverse Integer
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    4. Median of Two Sorted Arrays
    3. Longest Substring Without Repeating Characters
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/10436100.html
Copyright © 2011-2022 走看看