UVa 1440 只有下界的最小流

2021-06-16 23:34:48 字數 2911 閱讀 8796

分類: 圖論

uva && la

2013-07-21 16:48

112人閱讀收藏 

舉報題意:

給你一幅有向圖,你每次可以從任意點出發。圖中的每條邊至少要經過一次,問你至少要走幾次。

建圖:

設每個點i的入度減去出度為d[i], s為源點,t為匯點。

對於d[i] > 0的點i, 連邊

對於d[i] < 0的點i, 連邊

其它邊連法與輸入的邊相同。

問題:

對於輸入的每條邊下界為1,我們要求的是最小值,所以問題可以轉化為求該圖的最小流,

顯然,對於沒有下界的網路 其最小流就為零, 但該題的圖有下界,那麼如何求有下界的網路的最小流呢?

只有下界的最小流的解法:

先判斷該網路是否存在可行流,對於本題,顯然存在可行流。

如果可行流存在(假設可行流的值為f1),則從可行流出發,倒向求解。

即保持網路中的弧方向不變,將t作為源點,s作為匯點,反向流一次最大流後(假設求出的最大流為f2),

那麼原圖的最小流為f1 - f2。

輸出路徑:

求完該圖的最小流以後,假如邊流了c流量,那麼說明邊需要走c+1次。

對於以上的情況,新建一幅要求路徑的圖。

你可以建c+1條邊, 也可以加一條邊和乙個資訊(訪問次數c+1)。

我用了後者的作法,但在理論上我們把它看成c+1條邊。

我們可以計算出這幅圖每個點的d[i](入度減去出度)。

這裡要注意有可能沒有邊可以走,那麼只能搜到乙個點,這種情況不用輸出也不用更新d[i]

每次搜到一條路就停止dfs,然後

輸出路徑。

**:

[cpp]view plain

copy

#include 

#include 

#include 

#include 

using

namespace

std;  

const

intmaxn = 110;  

const

intinf = 1e9;  

#define pb push_back

#define mp make_pair

#define pii pair 

#define x first

#define y second

struct

edge   

edge(int

v, int

c, int

next) : v(v), c(c), next(next) {}  

} edge[maxn * maxn << 1];  

inthead[maxn], e;  

intn, m;  

ints, t;  

void

init()   

void

add(

ints, 

intt, 

intc)   

intd[maxn];  

vectoredges[maxn];  

intgap[maxn], dis[maxn], pre[maxn], cur[maxn];  

intsap(

ints, 

intt, 

intn)   

gap[0] = n;  

intu = pre[s] = s, aug = inf, maxf = 0, v;  

while

(dis[s] < n)   

maxf += aug;  

aug = inf;  

}  goto

loop;  

}  }  

intd = n;  

for(i = head[u]; ~i; i = edge[i].next)   

}  if

(!(--gap[dis[u]]))  

break

;  ++gap[dis[u] = d + 1];  

u = pre[u];  

}  return

maxf;  

}  bool

flag;  

intres[maxn], t;  

intans, cnt;  

void

dfs(

intu)   

if(!g) d[u]--, flag = 1;  

}  int

main()   

}  s = n; t = n + 1;  

for(i = 0; i < n; i++)  

if(d[i] < 0)  

add(i, t, -d[i]), ans -= d[i];  

else

if(d[i] > 0)  

add(s, i, d[i]);  

ans -= sap(s, t, t + 1);  

printf("%d\n"

, ans);  

for(i = 0; i < n; i++)  

edges[i].clear();  

for(i = 0; i < n; i++)  

for(j = head[i]; ~j; j = edge[j].next)  

if(!(j & 1))   

for(i = 0; i < n; i++)  

while

(d[i] < 0)   

}  }  

return

0;  

}  

乙隻有野心的小爬蟲

這個問題在程式設計師中的爭議很大,這裡不拉開情懷與逼格的爭議。對於大多數人,我的建議是 先暫時使用ide,這可以在學習的過程中讓你的精力主要集中在 的編寫上,對於執行和除錯也非常方便。但是你至少應該會一點vim的基礎操作,這樣可以方便你在伺服器部署 ctrl space 基本的 完成 類 方法 屬性...

做乙隻有追求的猿

昨天早上懷著忐忑的心情去面試 在中關村站下車時 空氣的濕度好像變的綿密了 果然 海淀居然在下雨?那好 去便利店買雨傘吧 結果可好 一堆人把雨傘搶光了 只有兩件雨衣了 沒辦法 硬著頭皮買雨衣吧 總不能淋感冒了不是 穿好雨衣的我看起來就是一外賣小哥 順著導航一路找過去發現不對 索性放棄不靠譜的導航直接找...

650 只有兩個鍵的鍵盤

最初在乙個記事本上只有乙個字元 a 你每次可以對這個記事本進行兩種操作 copy all 複製全部 你可以複製這個記事本中的所有字元 部分的複製是不允許的 paste 貼上 你可以貼上你上一次複製的字元。給定乙個數字n。你需要使用最少的操作次數,在記事本中列印出恰好n個 a 輸出能夠列印出n個 a ...