記錄反路徑的原因是要讓此水管的水能被重新分配,假設a b兩端,已有a流向b的水5單位,現以b當作目前所在的位置,如果想要從b流向a 2單位,那就等於在a端從原來的5單位分配2單位給當前路徑,就可以繼續流了,而b端則由(當前的水2單位)+(原有的5單位-分配出去的2單位=3單位)=5單位,還是5單位,代表此操作並不會改變之前的結果
還有一個關鍵就是找最短路徑
int rest[MAXN][MAXN],pre[MAXN],mi[MAXN];
bool bfs(int s){
queue<int> q;
memset(pre,-1,sizeof(pre)); //初始化為未走過
q.push(s);
pre[s]=s; //起點標記為走過
mi[s]=inf; //起點能用的網路流量初始為最大(為了求最小值)
while(!q.empty()){
int now=q.front();q.pop();
for(int i=1;i<=n;i++){
if(pre[i]==-1 && rest[now][i]){ //如果沒走過i且從now走到i的路還有流量
pre[i]=now; //記錄從哪裡來,以用來走inverse
mi[i]=min(mi[now],rest[now][i]); //記錄每條路徑的最小值
if(i==n) return true; //如果走到終點就直接回傳,求最短路徑
q.push(i);
}
}
}
return false; //走不到end point
}
int max_flow(){
cin >> n >> m;
for(int i=0;i<m;i++){
int u,v,w;
cin >> u >> v >> w;
rest[u][v]+=w; //流量可累計
}
int sum_flow=0;
while(bfs(1)){
int increase_flow=mi[n];
sum_flow+=increase_flow;
int now=n;
while(now!=1){
rest[pre[now]][now]-=increase_flow; //減少還能用的流量
rest[now][pre[now]]+=increase_flow; //應加inverse流量
now=pre[now]; //回朔
}
}
return sum_flow;
}
求刪除最少數量的邊能讓1不能走到N
想法:先討論要刪除幾條邊,每次bfs找能從1走到N的一條路徑,並把它標示成走過,接著找下一條路徑直到找不到為止,這就是上面的最大流演算法,只要每一條邊視權重為1即可,這樣要刪除的邊的個數就是最大流的答案,那要刪除哪條邊呢?可視為左邊中間右邊,左半邊包含起點(1),右半邊包含終點(N),注意到中間連接的部分,每條邊一定都被標示為走過,如果沒被標示過那上面在做最大流bfs的時候就還會找到增廣路徑,所以不合法,可以把中間部分想像成腰帶,束緊了連接左右兩邊的邊,在刪除的時候要刪除這些邊即可,我們可以從1節點dfs一次可走到的節點,因為有反向流,在左半邊的任何節點都會被遍歷到,右半邊任何節點都不會被遍歷到,因為反向流堵住了中間部分,讓dfs走不過去,遍歷完後,找節點i被走過 節點j沒被走過且(i,j)之間有邊的兩個點,此邊即為答案
cout << sum_flow << '\n';
dfs(1);
for(int i=1;i<=n;i++){
if(vis[i]){
for(int j=1;j<=n;j++){
if(!vis[j] && has_edge[i][j]) cout << i << ' ' << j << '\n';
}
}
}
or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Syncing