先判斷有無可行流,再求最大流
在上一題上下界流中,我們已經知道了怎麼判斷無源匯上下界網路流有無可行流
把每一天看成乙個點,每個女孩也看成乙個點,增加源和匯s、t,源向每一天連上[0,d]的邊,每一天與每個女孩如果有拍照任務的話連上[l,r]的邊,每個女孩與匯連上[g,oo]的邊,於是構成乙個有上下界的圖
所以這道題目我們可以轉換一下
只要連一條
t → s
的邊,流量為無窮,沒有下界,那麼原圖就得到乙個無源匯的迴圈流圖。接下來的事情一樣:原圖中的邊的流量設成自由流量
ci – bi
。新建源點
ss匯點
tt,求
mi,連邊。然後求
ss → tt
最大流,判是否滿流。
判定有解之後然後求最大流,資訊都在上面求得的殘留網路裡面。滿足所有下界時,從
s → t
的流量為後悔邊
s → t
的邊權!然後在殘留網路中
s → t
可能還有些自由流沒有流滿,再做一次
s → t
的最大流,所得到的最大流就是原問題的最大流
(內含兩部分:殘留的自由流所得到的流
+後悔邊
s → t)
。一些細節在**中有注釋
view code
#include#include
const
int max=2000;
const
int inf=1000000000;
struct
edge[1000000];
int e,head[max];
int gap[max],cur[max];
int pre[max],dis[max];
void add_edge(int s,int t,int c,int cc)
int min(int a,int b)
maxflow+=aug;
aug=-1;
}goto loop;}}
int mindis=n;
for(i=head[u];i!=-1;i=edge[i].next)
return maxflow;
}int n,m,e;
int s,t,ss,tt;
intin[max],low[100010];
bool solve()
sap(ss,tt,tt+1);
for(i=head[ss];i!=-1;i=edge[i].next)
if(edge[i].c) return
false;
return
true;
}int d[max];
int main()
e=0;
for(i=1;i<=n;i++)
}for(i=1;i<=n;i++) add_edge(s,i,d[i],0);
for(i=1;i<=m;i++) add_edge(i+n,t,inf,0);
add_edge(t,s,inf,0);//
s->t : 0 ,t->s : inf 構造無源匯上下界網路
int ans=0;
if(solve())
else printf("
-1\n
");puts("");
}return
0;}
上下界網路流初探
看文章各種不明真相.請教了一下iwtwiioi大牛.大致有個理解.建模過程 1.拆邊.對於每一條給出的有向邊 u,v,c,d 其中c指下界,d指上界,那麼在實際的圖中連三條只有上界沒有下界的邊 s,v,c u,t,c u,v,d c 其中s是超級源,t是超級匯.不同於題目給出的源與匯 一條是超級源連...
上下界網路流專題
給定n點m邊無向圖,用k個人從起點出發,乙個人走一條路代價為路的長度li,你希望按照0,1,2,n的順序依次經過這些點,其中經過的定義是任何1人經過該點,問k個人最小的道路總和。n 150,m 20 000,1 k 10,li 10 000 考慮每次只有1個人走1步,已經過t點,則每次其中一人走向t...
有上下界網路流
前言 下面寫得只是一些十分基礎的東西,是給我以後自己看的,想要徹底弄明白這個內容,推薦去看liu runda。注 為了方便,下面所有的 x,y,l,r 都表示一條從x連向y,流量下界為l,流量上界為r的邊。問題簡述 給出乙個有向圖,每條邊有流量上下界,沒有源點和匯點,要求找到一種流的方法,使得每個點...