用於求任意兩個點的最小割(最大流)
最小割樹建造方法:
類似於分治
在當前點集中選擇任意兩個點作為源點、匯點,跑最小割g
兩個點之間連樹邊,邊權為g
把當前點集中和源點聯通的能到的放進乙個集合裡,與t聯通的放進另乙個集合裡。然後分治下去
注意,每次跑最小割g是在全域性跑。
n次最小割
建出樹來之後,任意兩點的最小割,就是兩點樹上路徑的邊權最小值。
證明不知。
可以證明最小是這個最小值,但是感覺不能證明能取到=。
**:(找聯通塊的話,用dfs染色即可)
【模板】最小割樹(gomory-hu tree)
#include#define il inline#define reg register int
#define numb (ch^'0')
using
namespace
std;
typedef
long
long
ll;il
void rd(int &x)
namespace
miraclee[
2*m],bian[2*m];
struct
bbbbbb[m];
int hd[n],cnt=1
;void add(int x,int y,int
z)int
pre[n],tot;
void add_c(int x,int y,int
z)int
d[n];
int dfs(int x,int
flow)
}return flow-res;
}int
q[n],l,r;
bool
bfs()}}
return
false;}
int dinic(int x,int
y)
int maxflow=0
;
int flow=0
;
while
(bfs())
return
maxflow;
}int
ptr;
intmem[n],b[n],co[n];
bool
in[n];
void fin(intx)}
void divi(int l,int
r)
for(reg i=l;i<=r;++i)
divi(l,pp);divi(qq,r);
}int fa[n][13],mi[n][13
];int
dep[n];
void dfs2(int x,int
deep)
}int slo(int x,int
y) }
if(x==y) return
ans;
for(reg i=12;i>=0;--i)
}ans=min(ans,min(mi[x][0],mi[y][0
]));
return
ans;
}int
main()
for(reg i=1;i<=n;++i) mem[i]=i;
divi(
1,n);
dfs2(
1,1);
for(reg j=1;j<=12;++j)
}intt;
rd(t);
dep[
0]=-1
;
while(t--)
return0;
}}signed main()
/*author: *miracle*
date: 2018/12/16 22:45:00
*/
還有兩個模板題;[zjoi2011]最小割
[cqoi2016]不同的最小割
最小割樹 學習筆記
你最終會得到圖的一棵生成樹,然後 a,b 兩點的最小割即是生成樹上 a,b 間路徑中,權值最小的那條邊。很神奇。那你怎麼建出這個樹來呢?首先,最小割等於最大流。你需要乙個 text 模板。故此,你在當前的點集中選定隨意選定兩個點 a,b 求出它們最小割 w 生成樹上增加一條邊 a b w 此時最小割...
學習 最小割樹
及時學習了一波最小割樹。我們有乙個定理 對於n個點的一張圖,本質不同的最小割最多只有n 1種。那麼我們一定可以將原圖構成一棵樹,使得原圖中兩個點 x,y 的最小割等於這棵樹上兩點 x,y 的最小割。構造方法 我們選取集合中的兩個點 x,y 然後跑乙個最小割後將集合劃分為x集合 x可以在殘量網路上到達...
最小割樹 Luogu P4897 最小割樹
給定乙個nn個點mm條邊的無向連通圖,多次詢問兩點之間的最小割 兩點間的最小割是這樣定義的 原圖的每條邊有乙個割斷它的代價,你需要用最小的代價使得這兩個點不連通 輸入格式 第一行兩個數n,mn,m 接下來mm行,每行33個數u,v,wu,v,w,表示有一條連線uu與vv的無向邊,割斷它的代價為ww ...