图论 —— 网络流 —— 费用流 —— MCMF 算法
生活随笔
收集整理的這篇文章主要介紹了
图论 —— 网络流 —— 费用流 —— MCMF 算法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【概述】
EK 算法是每次用廣搜尋找一條最短的增廣路,然后沿其增廣,而 MCMF 算法是在 EK 算法的基礎上,每次用 SPFA 計算圖的距離標號,然后沿著可行邊進行增廣,即將 EK 算法中的 bfs 替換為 SPFA 求最短路,邊權為該邊的單位流量花費,即改變遍歷的優先級來實現。
【基本思想】
1.每次查找是否存在從源點到匯點可增廣的路徑(源點到匯點的最短路且路徑上的所有邊均不能滿流),并用 pre[i] 記錄路徑上到達點 i 的邊的編號。
2.若存在這樣的路徑,則從匯點沿著 pre 數組向前找,找到該路徑上可以增廣的流量 Min(所有邊中剩余流量最小的),再從匯點遍歷一次,正向邊增加流量 Min,反向邊減少 Min,總費用累加 Min * edge[i].cost,總流量累加 Min
【實現】
struct Edge{int from,to;int cap,flow;int cost;//費用int next;//指向下一條邊的編號 }edge[N]; int head[N],tot; int dis[N];//單源最短路徑 bool vis[N];//SPFA中用于判斷是否在隊列 int pre[N];//記錄從S到i的最小費用路徑上的最后一條弧編號 void addEdge(int x,int y,int cap,int cost){edge[tot].from=x;edge[tot].to=y;edge[tot].cap=cap;edge[tot].flow=0;edge[tot].cost=cost;edge[tot].next=head[x];head[x]=tot++;edge[tot].from=y;edge[tot].to=x;edge[tot].cap=0;edge[tot].flow=0;edge[tot].cost=-cost;edge[tot].next=head[y];head[y]=tot++; } bool SPFA(int S,int T) {queue<int> Q;memset(dis,INF,sizeof(dis));memset(vis,false,sizeof(vis));memset(pre,-1,sizeof(pre));dis[S]=0;Q.push(S);while(!Q.empty()) {int x=Q.front();Q.pop();vis[x]=false;for(int i=head[x];i!=-1;i=edge[i].next) {int y=edge[i].to;int cost=edge[i].cost;int cap=edge[i].cap;int flow=edge[i].flow;if(dis[y]>dis[x]+cost&&cap>flow) {dis[y]=dis[x]+cost;pre[y]=i;if(!vis[y]){vis[y]=true;Q.push(y);}}}}return pre[T]!=-1; } void MCMF(int S,int T,int &flow,int &cost){while(SPFA(S,T)){//每次尋找花銷最小的路徑int minn=INF;for(int i=pre[T];i!=-1;i=pre[edge[i^1].to])//尋找最小增廣流minn=min(minn,edge[i].cap-edge[i].flow);for(int i=pre[T];i!=-1;i=pre[edge[i^1].to]) {edge[i].flow+=minn;edge[i^1].flow-=minn;cost+=edge[i].cost*minn;//增廣流的花銷}flow+=minn;//總流量增加} } int main(){int n,m;scanf("%d%d",&n,&m);tot=0;memset(head,-1,sizeof(head));for(int i=1;i<=n;i++){int x,y,cap,cost;scanf("%d%d%d%d",&x,&y,&cap,&cost);addEdge(x,y,cap,cost);//正向邊}int cost=0,flow=0;//最小費用、最大流int S=1,T=n;//源點與匯點MCMF(S,T,flow,cost);printf("minCost:%d\n",cost);printf("maxFlow:%d\n",flow);return 0; }?
總結
以上是生活随笔為你收集整理的图论 —— 网络流 —— 费用流 —— MCMF 算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: The more, The Better
- 下一篇: 找连续数(HDU-5247)