题意给一张流量网,问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\n",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();
}