有源匯上下界最小費用可行流。
將每個國家拆點。
源點向乙個新建節點連一條上界為總人數下界為0費用為0的邊。
新建節點向每個國家的入點連一條上界為正無窮下界為0費用為0的邊。
每個國家的入點向出點連一條上下界均為該國家訪問人數費用為0的邊。
每個國家的出點向匯點連一條上界為正無窮下界為0費用為0的邊。
對於國家i能到國家j,i的出點向j的入點連一條上界為正無窮下界為0費用為機票費的邊。
然後對圖求一邊有源匯上下界最小費用可行流即可得出最小費用。
具體做法是先將所有邊的下界乘費用相加,這一部分是必須的費用,然後按照「有源匯上下界可行流」建圖,從超級源向超級匯跑一遍最小費用最大流,兩個費用相加即為答案。
至於本題本身的建圖思路,與bzoj1927星際競速類似,下面放乙份十分良心的題解。
天地良心無與倫比誰與爭鋒的一篇題解
1 #include2 #include3 #include4 #include5 #include6using
namespace
std;
7const
int dian=305;8
const
int bian=100005;9
const
int inf=0x3f3f3f3f;10
inth[dian],nxt[bian],ver[bian],val[bian],cos[bian];
11int
d[dian],v[dian],with[dian],minn[dian];
12int
in[dian],out
[dian];
13int
n,m,tot,aa,mf;
14int
s,t,ss,tt;
15void add(int a,int b,int c,int d,int
e)21
bool
tell()44}
45}46}
47if(d[t]==0x3f3f3f3f)48
return
false;49
return
true;50
}51intzeng()
56return minn[t]*d[t];57}
58int
dinic_cost()
64int
main()
81for(int i=1;i)
82for(int j=1;j<=n-i;j++)
87 add(tt,ss,0,inf,0
);88
for(int i=1;i<=tt;i++)
94 printf("
%d",mf+dinic_cost());
95return0;
96 }
注意題意敘述不清,每個人可以從任意乙個國家開始走。
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是真正的匯。這樣構...
BZOJ2055 80人環遊世界
上下界最小費用流 限制點訪問量 拆點 i,i 建圖 1.s s m,m 0 2.s i 0,inf 0 i t 0,inf 0 3.i j 0,inf x 4.i i vi,vi 0 然後就是上下界流的常見套路啦 根據 調整 原則 先是每個點點權為di ini outi 然後 0的連源點 0的連匯點...
bzoj2055 80人環遊世界(可行流)
傳送門 表示完全看不懂最小費用可行流 據某大佬說 我們考慮拆點,然後進行如下連邊 s 向 a i 連邊,權值 0 容量 0,m a i 向 a i 連邊,權值 0 容量 v i,v i 如果存在邊 i,j 則連邊 a i a i 權值為 w 容量 0,m a i 向 t 連邊,權值 0 容量 0,m...