link
無特殊說明費用都是0
新建源點s
ss和匯點t
tt,新建虛擬限制節點xun
ixuni
xuni s
ss連向xun
ixuni
xuni
流量[ 0,
m]
[0,m]
[0,m
]的邊,表示可以派出的人不能超過mmm
x un
ixuni
xuni
連向每個點流量[0,
inf]
[0,inf]
[0,inf
]的邊,表示可以派出任何人去這個點
對於邊(x,
y,w)
(x,y,w)
(x,y,w
),讓x+n
x+nx+
n連向y
yy流量[0,
inf]
[0,inf]
[0,inf
]費用w
ww的邊,表示邊之間的轉移
對於每個點x
xx,讓x
xx連向x+n
x+nx+
n流量[vx
,vx]
[v_x,v_x]
[vx,v
x]的邊,表示必須經過v
xv_x
vx次
對於每個點連向t
tt流量為[0,
inf]
[0,inf]
[0,inf
],表示可以在任何點結束
然後t
tt連向s
ss流量為[0,
inf]
[0,inf]
[0,inf
]的邊,也就是讓s,t
s,ts,
t滿足流量守恆
新建s sss
ss和t ttt
tt,補齊圖中每個點的流量
如此一來,就是一張有源匯的網路圖,可以跑最大流找出可行流
但這裡是需要最小化費用,那麼從ssss
ss向t ttt
tt跑最小費用最大流即可
#include
using
namespace std;
const
int inf =
1e9;
const
int maxn =
3e5+10;
int v[maxn]
,in[maxn]
,out[maxn]
;int n,m,s,t,xuni,ss,tt,ans;
struct edged[maxn]
;int head[maxn]
,cnt=1;
void
add(
int u,
int v,
int l,
int r,
int w)
,head[u]
= cnt;
d[++cnt]
=( edge )
,head[v]
= cnt;
}int flow[maxn]
,dis[maxn]
,pre[maxn]
,vis[maxn]
,ned;
bool
spfa
(int s,
int t)}}
return dis[t]
!=inf;
}int
dinic
(int s,
int t)}if
( ned!=0)
//沒有滿流,說明不存在可行流
return ans;
}void
build()
for(
int i=
1;i<=n;i++
)for
(int j=i+
1;j<=n;j++
)for
(int i=
1;i<=t;i++
)add
(t,s,
0,inf,0)
;//使得源點和匯點滿足流量守恆
}int
main()
洛谷P4553 80人環遊世界
題意 有m個人,給定n個城市構成dag。每個城市恰好有vi個人經過,每條邊有費用。每個人自選起點,終點。求最小費用。解 首先拆點,連邊,流量為 vi,vi 然後做有上下界有源匯最小費用可行流即可。1 include 2 include 3 include 4 include 5 include 6 ...
BZOJ2055 80人環遊世界
題解 總算a掉了,各種蛋疼。int main for1 i,n for2 j,i 1,n for1 i,n insert i n,t,0,inf,0 insert t,s,0,inf,0 mcf printf d n mincost return0 s是附加源,sss是真正的源,t是真正的匯。這樣構...
bzoj 2055 80人環遊世界
有源匯上下界最小費用可行流。將每個國家拆點。源點向乙個新建節點連一條上界為總人數下界為0費用為0的邊。新建節點向每個國家的入點連一條上界為正無窮下界為0費用為0的邊。每個國家的入點向出點連一條上下界均為該國家訪問人數費用為0的邊。每個國家的出點向匯點連一條上界為正無窮下界為0費用為0的邊。對於國家i...