這道題跟求最大流的時候差不多。
都是先構造可行流,然後判斷是否可行,
可行的話,就利用殘餘流量,構造從匯點t跑到源點s的最大流,
如何求出答案呢。
在第一次求可行流的dinic後,跟求最大流的時候一樣,從t到s是可行流的流量;
這個時候t到s的反向邊,也就是s到t的流量就是t到s流的量(因為t到s定義權值為inf,要從這條邊算出來,得用inf去減到這條邊剩下的才是答案,有點麻煩)
所以反向邊是個便捷的求法。
所以在第一次dinic之後,t到s的反向便的流量就是可行流的流量;
然後我們再從t到s跑最大流,看最大能跑掉多少,就是最後的答案。 (這裡肯定不會影響可行流!,因為已經在第一次dinic的時候保證了可行(即sum==tmpp))
求第二次dinic的時候,要將s跟t之間的邊給去掉。
1 #include2 #include3 #include4 #include5 #include6
using
namespace
std;
7 typedef long
long
ll;8
const ll maxn=51000;9
const ll inf=0x3f3f3f3f3f3f3f3f;10
ll vis[maxn];
11 ll head[maxn],level[maxn]; //
前者為鄰接表必要資料,後者為dinic的層 資料
12 ll in[maxn]; //
一條邊的初始流量(最低值 也就是定為下界)
13 ll limit[maxn]; //
limit為該點的流量 小於0的時候是流出多
14//
ll bh[maxn];
//一條邊的反向邊的流量(正向邊流出了多少,反向邊就是多少)
15//
所以用初始的下界流量+上這個方向邊的流量就是最終答案;
16//
那麼為什麼不直接正向呢???
17//
廢話 正向求比較麻煩嘛。 原本的值是可以流的量,正向邊流出去後
18//
那麼答案就是可以流的量減去剩餘的量就是答案;
19//
所以還不如直接求反向呢
20 ll num; //
鄰接表21
void
init()
2226
struct
node
27g[maxn*12
];30
ll bfs(ll s,ll t)
3145}46
}47return
level[t];48}
49ll dfs(ll s,ll t,ll f)
5064}65
}66//if(ans==0) level[s]=0;
67return
ans;68}
69ll dinic(ll s,ll t)
7078
return
ans;79}
80void
build(ll u,ll v,ll w)
8194
intmain()
95107 ll s=0;ll t=n+1
;108 ll sum=0
;109
for(ll i=1;i<=n;i++)
113build(t,s,inf);
114//
其實這裡應該有上面的limit的變化 只是因為這裡的w1為0,所以省略不寫。
115 ll tmpp=dinic(s,t);
116if(tmpp!=sum) printf("
please go home to sleep\n");
117else
123return0;
124 }
117 有源匯有上下界最小流
題目描述 n nn 個點,m mm 條邊,每條邊 e ee 有乙個流量下界 lower e text e lower e 和流量上界 upper e text e upper e 給定源點 s ss 與匯點 t tt,求源點到匯點的最小流。輸入格式 第一行兩個正整數 n nn m mm s ss t...
有源匯有上下界最大 最小流
建圖還是要想一想的.寫一下吧 首先根據有源匯可行流建圖,正向附加邊滿流證明有可行流 然後在這個殘量網路上刪掉 t,s,oo 這條邊,跑 s t 最大流就是最大流,t s 最大流就是最小流 include define int long long define ll long long define ...
有源匯上下界最小流 模板
這只是 其中一種 做法 這只是其中一種做法 這只是其中一 種做法 我暫時還沒有理解,只是先放個模板而已 首 先還 是根據下 界來建圖 原圖源 點s,匯 點t 首先還是根據下界來建圖,原圖源點s,匯點t 首先還是根據 下界來建 圖,原圖 源點s,匯點t 然 後因 為流量守 恆,新建 超級源s 1和超級...