• 343E


    题意给一张流量网,问n-1天每天选不同的点,往任意未选过的点走管网输送流量使得能获得的流量和最大

    输出流量和和输送序列

    首先Gomory-Hu的定义和代码参考自这里

    大体上就是从网络图上生成一棵树,树的性质满足两点路径最小边权等于两点在网络图上的最大流

    有了这样一棵树就可以每次贪心选最小的一条边,保证现在边的两侧走完再走这条边

    因为这样这条边就只走了一次,最小化了总流量的限制,然后两边分治

    #include<bits/stdc++.h>
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    #include<string.h>
    #include<iostream>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<iomanip>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define FOR(a) for(int i=1;i<=a;i++)
    const int inf=0x3f3f3f3f;
    const int maxn=200+9;  
    
    struct EDGE{
    	int from,to,cap,flow;
    };
    vector<EDGE>edges;
    vector<int>c[maxn];
    
    int S,T;
    bool visit[maxn];
    int depth[maxn];
    int cur[maxn];
    void clear_graph(){
    	edges.clear();for(int i=0;i<maxn;i++)c[i].clear();
    }
    void clear_flow(){
    	int sz=edges.size();
    	for(int i=0;i<sz;i++)edges[i].flow=0;
    }
    void addedge(int from,int to,int cap){
    	EDGE tmp=(EDGE){from,to,cap,0};
    	edges.pb(tmp);
    	tmp=(EDGE){to,from,cap,0};
    	edges.pb(tmp);
    	int tot=edges.size()-2;
    	c[from].pb(tot);
    	c[to].pb(tot+1);
    }
    bool BFS(void){  
        memset(visit,0,sizeof(visit));  
        memset(depth,-1,sizeof(depth));  
        queue<int> Q;  
        Q.push(S);visit[S]=true;depth[S]=0;  
        while(!Q.empty()){  
            int x=Q.front();Q.pop();  
            for(int i=0;i<c[x].size();i++){  
                EDGE &now=edges[c[x][i]];  
                if(!visit[now.to]&&now.cap>now.flow){  
                    visit[now.to]=true;  
                    depth[now.to]=depth[x]+1;  
                    Q.push(now.to);  
                }  
            }  
        }  
        return visit[T];  
    }  
    int DFS(int x,int a){  
        if(x==T||!a) return a;  
        int flow=0,cf=0;  
        for(int i=cur[x];i<c[x].size();i++){  
            cur[x]=i;  
            EDGE &now=edges[c[x][i]];  
            if(depth[x]+1==depth[now.to]){  
                cf=DFS(now.to,min(a,now.cap-now.flow));  
                if(cf){  
                    flow+=cf;  
                    a-=cf;  
                    now.flow+=cf,edges[c[x][i]^1].flow-=cf;  
                }  
                if(!a) break;  
            }  
        }  
        if(!flow) depth[x]=-1;  
        return flow;  
    }  
    int Dinic(void){  
        int flow=0;  
        while(BFS()){  
            memset(cur,0,sizeof(cur));  
            flow+=DFS(S,inf);  
        }  
        return flow;  
    } 
    
    int N,M;
    int fa[maxn],falen[maxn];
    int now;
    void find_min(int x,int fa){	//找x子树中最小的边
    	for(int i=0;i<c[x].size();i++){
    		EDGE &e=edges[c[x][i]];
    		if(e.to!=fa && e.cap!=-1){
    			if(now==-1||e.cap<edges[now].cap)now=c[x][i];
    			find_min(e.to,x);
    		}
    	}
    }
    void solve(int x){
    	now=-1;
    	find_min(x,0);
    	if(now==-1){
    		printf("%d ",x);
    		return;
    	}
    	edges[now].cap=edges[now^1].cap=-1;
    	int p=now;
    	solve(edges[p].from);
    	solve(edges[p].to);
    }
    int ans=0;
    void build_tree(){
    	for(int i=1;i<=N;i++)fa[i]=1;
    	for(int i=2;i<=N;i++){
    		clear_flow();
    		S=i,T=fa[i];
    		falen[i]=Dinic();
    		BFS();
    		for(int j=i+1;j<=N;j++)
    			if(visit[j]&&fa[j]==fa[i])fa[j]=i;
    	}
    	clear_graph();
    	for(int i=2;i<=N;i++)
    		addedge(i,fa[i],falen[i]),ans+=falen[i];
    }
    void answer(){
    	printf("%d
    ",ans);
    	solve(1);
    	puts("");
    }
    void init(){
    	scanf("%d%d",&N,&M);
    	int a,b,w;
    	for(int i=1;i<=M;i++){
    		scanf("%d%d%d",&a,&b,&w);
    		addedge(a,b,w);
    	}
    }
    int main(){
    	init();
    	build_tree();
    	answer();
    }



  • 相关阅读:
    前端之JQuery:JQuery文档操作
    前端之JQuery:JQuery属性操作
    前端之JQuery:JQuery基本语法
    前端之JavaScript:JS之DOM对象三
    前端之JavaScript:JS之DOM对象二
    初始django
    mysql 索引
    多表查询
    单表查询
    外键的三种形式
  • 原文地址:https://www.cnblogs.com/Drenight/p/8611251.html
Copyright © 2020-2023  润新知