以下的內容僅是一些對上下界網路流的補充說明,基礎概念都沒有涉及,但是有一些注意點。
這裡的三道題(無源匯上下界可行流,有源匯上下界最大流,有源匯上下界最小流)是採用\(loj\)的模板,題號是\(115-117\)。
給定乙個無源匯的圖,流量有上下界,問乙個可行流。
無源匯有上下界可行流
每個點的容量轉化為上界\(-\)下界,並統計每個點的多餘流量,新建源匯點\(ss,tt\)連那些多餘的流量,然後跑最大流即可。如果那些源匯邊上不滿流,就沒有可行流,否則在流量上加上該邊的下界即可。
注意:乙個與意識上理解起來不同的地方,如果入流\(>\)出流,應該是\(ss\)向\(i\)連邊,否則是\(i\)向\(tt\)連邊。
跑完最大流後的圖上,正邊是殘量網路,反邊才是跑了的流量,用反邊\(+\)下界才是答案(其實用上界\(-\)正邊也對)。
#include#include#includeusing namespace std;
const int maxn=210,maxm=31000,inf=0x7fffffff;
int n,m,ss,tt,tot,head[maxn],dis[maxn],cur[maxn],d[maxn];
struct node
edge[maxm];
queueq;
int read()
void add(int u,int v,int w,int rg=0)
; head[u]=tot;
}void link(int u,int v,int w,int rg=0)
bool bfs()
} }return dis[tt];
}int dfs(int u,int flow)
} return flow-res;
}void dinic()
}int main()
for (i=1;i<=n;i++)
if (d[i]!=0)
dinic();
int fl=0;
for (i=head[ss];i;i=edge[i].nxt)
if (edge[i].w)
if (!fl)
for (i=head[tt];i;i=edge[i].nxt)
if (edge[i^1].w)
if (fl)
puts("no");
else
return 0;
}
問有乙個有源匯的圖,流量有上下界,問最大流。
有源匯上下界最大流
先判斷可行性,還是加入\(ss\)和\(tt\)來判斷,但是\(s\)和\(t\)處的流量不平衡,所以我們讓\(t\)向\(s\)連一條邊\(inf\),這樣就肯定平衡了,然後跑\(ss\)到\(tt\)的最大流,判斷是否可行,注意這條邊的流量就是可行流的大小。然後刪掉這條邊,再跑\(s\)到\(t\)的最大流,這個最大流\(+\)可行流就是答案了。
注意是刪掉那條\(t-s\)的邊,不是刪掉\(t\)和\(s\)或者是\(tt\)和\(ss\)的這幾個點。還有一種方法是不刪這條邊,然後直接跑\(s\)到\(t\)的最大流,因為肯定不會選\(t-s\)這條邊,但是反邊一定選(為什麼我還沒懂),所以可行流就加上了。或者直接二分可行流的大小,然後賦值到那條\(t-s\)邊上也可以(不太懂怎麼實現)。
#include#include#includeusing namespace std;
const int maxn=210,maxm=20500,inf=0x7fffffff;
int n,m,s,t,ss,tt,tot,head[maxn],cur[maxn],dis[maxn],d[maxn];
struct node
edge[maxm];
queueq;
int read()
void add(int u,int v,int w)
; head[u]=tot;
}void lnk(int u,int v,int w)
bool bfs(int s,int t)
} }return dis[t];
}int dfs(int u,int flow,int t)
} return flow-res;
}int dinic(int s,int t)
return ans;
}int main()
for (i=1;i<=n;i++)
if (d[i]!=0)
lnk(t,s,inf);
maxflow-=dinic(ss,tt);
if (maxflow)
maxflow=edge[tot].w;
edge[tot].w=edge[tot^1].w=0;
printf("%d\n",maxflow+dinic(s,t));
return 0;
}
問有乙個有源匯的圖,流量有上下界,問最小流。
有源匯上下界最小流
前面連邊同上下界最大流,考慮反邊的最大減少量\(=\)正邊的最小增加量,所以刪邊後可行流\(-\)
\(t\)到\(s\)的最大流即為最小流。
最好和\(0\)取個\(\max\)再輸出,因為不知道最小流會不會\(<0\)不合法。
#include#include#includeusing namespace std;
typedef long long ll;
const int maxn=50010,maxm=350020;
const ll inf=0x7fffffffffffffffll;
int n,m,s,t,ss,tt,tot,head[maxn],cur[maxn],dis[maxn];
ll d[maxn];
struct node
edge[maxm];
queueq;
ll read()
void add(int u,int v,ll w)
; head[u]=tot;
}void lnk(int u,int v,ll w)
bool bfs(int s,int t)
} }return dis[t];
}ll dfs(int u,ll flow,int t)
} return flow-res;
}ll dinic(int s,int t)
return ans;
}int main()
for (i=1;i<=n;i++)
if (d[i]!=0)
lnk(t,s,inf);
maxflow-=dinic(ss,tt);
if (maxflow)
maxflow=edge[tot].w;
edge[tot].w=edge[tot^1].w=0;
printf("%lld\n",max(0ll,maxflow-dinic(t,s)));
return 0;
}
上下界網路流總結
orz zhhx orz yyb orz aysn 無源匯可行流 每條邊取 l i 最大流調整 有源匯可行流 e t,s,inf 無源匯可行流 有源匯最小流 有源匯可行流 去掉 inf 邊 t rightarrow s 最大流 有源匯最大流 有源匯可行流 去掉 inf 邊 s rightarrow ...
上下界網路流總結
我們普通的網路流題中每條邊有乙個容量,或者是說每條邊實際流量在 0,容量 之間 帶上下界的網路流意思就是說每條邊有乙個最小流量和乙個最大流量 問題大概分為三種 1.無源匯帶上下界可行流 假設一條邊是u v的 lower,upper 我們可以把這條邊拆成兩條,一條邊必須流過 0,lower 的流量,另...
有上下界的網路流 模板
在還沒開始之前先貼乙個 覺得講的挺好的 n 個點,m 條邊,每條邊 e 有乙個流量下界 lower e 和流量上界 upper e 求一種可行方案使得在所有點滿足流量平衡條件的前提下,所有邊滿足流量限制。輸入格式 第一行兩個正整數 n m 之後的 m 行,每行四個整數 s t lower upper...