• 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;
    }
    
  • 相关阅读:
    个人管理:2,3月微薄整理
    ORM相关图片整理
    LmgORM项目 实体类转换器
    (转)Enterprise Architect 7.0入门教程
    禁止右键复制的代码
    UML示例图(转)学习
    Flash FMS Helloword
    模拟生成Guid
    Flash Media Server安装
    WebSphere创建删除概要文件
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/10436100.html
Copyright © 2020-2023  润新知