最小費用最大流(拆邊)

2021-07-24 16:19:38 字數 1627 閱讀 4200

題目大概意思是,有n個城市m條邊,要從1城市到n城市運送k的物品,求最少花費,每個邊有乙個係數ai花費的錢是ai*這條邊上運送物資數的平方,比如在係數為3的邊上運送了2的物品,則需要3*2*2的花費;

思路:由於每條邊的容量不超過5,所以可以把每一條邊拆成容量條流量為1的邊,他們的花費分別為1*ai,3*ai,5*ai,7*ai,9*ai;

花費依次遞增,然後每次找的最短路都是最小的,前幾次的加起來就是總的花費;比如前兩次的加起來就是4*ai,又因為每一條邊容量為1,則前兩次的總花費為ai*2*2也就是4*ai;

源點向1建容量為k花費0,n向匯點建容量為1花費為0,根據這個建圖,跑最大流最小費用即可,如果最大流不是k則輸出-1;

#include//每次找費用的最短路,更新殘留網路圖直到找不到最短路為止

#include//最大費用 權值取負值 結果取負值

#include

#include

#include

using

namespace

std;

const

int inf=0x3f3f3f3f;

struct node

node[1001000];

int head[1001000],cont,sumflow;

int vis[101000],dist[101000];

int pre[101000];

void init()

void add(int u,int v,int w,int cost)//建圖

// }

node[cont].u=u,node[cont].v=v;

node[cont].w=w,node[cont].cost=cost;

node[cont].next=head[u],head[u]=cont++;

node[cont].u=v,node[cont].v=u;

node[cont].w=0,node[cont].cost=-cost;//反向邊費用為負的

node[cont].next=head[v],head[v]=cont++;

}int spfa(int st,int ed)//尋找最短路

dist[st]=0;

vis[st]=1;

q.push(st);

while(!q.empty())}}

}if(dist[ed]==inf) return

0;//找不到最短路

return1;}

int mcmf(int st,int ed)

mincost+=dist[ed];//每次找到最短路後更新最小費用

flow+=1;//更新最大流

}sumflow=flow;//最大流

return mincost;

}int main()

}add(n,ed,k,0);

int ans=mcmf(st,ed);//最小費用最大流

if(sumflow!=k)

printf("-1\n");

else

printf("%d\n",ans);

}return

0;}

題目鏈結請戳這裡

hdu 3667(拆邊 最小費用最大流)

思路 由於花費的計算方法是a x x,因此必須拆邊,使得最小費用流模板可用,即變成a x的形式。具體的拆邊方法為 第i次取這條路時費用為 2 i 1 a i 5 每條邊的容量為1。如果這條邊通過的流量為x,那正好sigma 2 i 1 1 1 include2 include3 include4 i...

最小費用最大流模板(存邊)

函式功能介紹 addedge from,to,w,res 新增一條 x y,費用為w,殘量為res的邊,並一起新增其反向邊,由於從0號開始,相鄰兩個數代表的邊互為反向邊 即i號邊的反向邊是 i 1 spfa.init n 初始化點數n spfa.find s,t 在 源點為s,匯點為t的圖中尋找最小...

最小費用最大流

網 絡流的基本問題為 設乙個有向賦權圖g v,e v 其中有兩個特殊的節點s和s s稱為發點,s 稱為收點。圖中各 邊的方向和權數表示允許的流向和最大可能的流量 容量 問在這個網路圖中從發點流出到收點匯集,最大可通過的實際流量為多少?流向的分布情況為怎樣?設有乙個網路圖g v,e v e中的每條邊 ...