1. 程式人生 > >讓菜雞講一講費用流(EK)

讓菜雞講一講費用流(EK)

getch name 處理 getchar() har con += spa 兩個

讓我再講一個故事吧。

又有一些小精靈要準備從銀月城(S)遷徙到Nibel山(T)。

這兩個地方之間的道路構成了一個網絡。

每個道路都有它自己的容量,這決定了每天有多少小精靈可以同時從這兒通過。

和上一篇不同的是,由於上次遷徙的規模很大,

吸引了其它一些種族的註意,

這次每條道路都會有一些人/獸人/哥布林/...向精靈們征收過路費,

現在精靈們想知道,在花費最小的情況下,它們遷徙的速度最大是多少只每天。

費用流=最小費用最大

在要求流最大的情況下要求費用最小,好像原來的isap已經派不上用場了呢!

讓我們回到最樸實的EK算法上。

EK算法每一次只尋找一條增廣路,

這帶給它解決這一個方面的問題的得天獨厚的優勢。

這是原來的EK算法:

int BFS()
{
    /*找到一條增廣路*/
}
int ek()
{
    /*對找到的增廣路進行一系列處理*/
}

我們用BFS找增廣路。

想象一下,

既然要求費用最小

我們就把費用作為路徑長度

之後每一次跑一遍最短路

那麽就可以保證花費最小了!


所以,我們只要把原來的BFS()改成spfa()或者dijkstra()就好啦

ps.一般dijkstra只能跑不帶負權邊的圖,
但是有一種特殊的技巧可以把邊權魔改成正的。

以下是拿辣雞spfa跑的費用流

#include<bits/stdc++.h>
using namespace std;
typedef
pair<int,int> pii; #define mp(a,b) make_pair(a,b) #define ll first #define rr second inline int gotcha() { register int a=0,b=1,c=getchar(); while(!isdigit(c))b^=a=='-',c=getchar(); while(isdigit(c))a=a*10+c-48,c=getchar(); return b?a:-a; } const int _ = 5002 , __ = 50002<<1
, inf = 0x3f3f3f3f; int to[__],ne[__],v[__],co[__],he[__]={0},ecnt=1; int n,m,dis[_],pe[_],pv[_],S,T; bool ed[_]; void adde(int a,int b,int c,int d){to[++ecnt]=b,v[ecnt]=c,co[ecnt]=d,ne[ecnt]=he[a],he[a]=ecnt;} queue<int> q; int spfa() { memset(dis,63,sizeof(dis)),memset(ed,0,sizeof(ed)); while(!q.empty())q.pop(); register int i,a; q.push(S),ed[S]=1,dis[S]=0; while(!q.empty()) { a=q.front(),q.pop();ed[a]=0; for(i=he[a];i;i=ne[i]) if(v[i]>0 && dis[to[i]]>dis[a]+co[i]) { dis[to[i]]=dis[a]+co[i]; pe[to[i]]=i,pv[to[i]]=a; if(!ed[to[i]])ed[to[i]]=1,q.push(to[i]); } } return dis[T]<inf; } pii mfmc() { register int i,sco=0,sfl=0,flw; while(spfa()) { flw=inf; for(i=T;i!=S;i=pv[i])flw=min(flw,v[pe[i]]); for(i=T;i!=S;i=pv[i])v[pe[i]]-=flw,v[pe[i]^1]+=flw; sco+=flw*dis[T],sfl+=flw; } return mp(sfl,sco); } int main() { register int i,j,k,a,b; register pii tmp; n=gotcha(),m=gotcha(),S=gotcha(),T=gotcha(); for(i=1;i<=m;i++) { j=gotcha(),k=gotcha(),a=gotcha(),b=gotcha(); adde(j,k,a,b),adde(k,j,0,-b); } tmp=mfmc(); printf("%d %d",tmp.ll,tmp.rr); return 0; }

這就不寫偽代碼了吧!?

以後補

讓菜雞講一講費用流(EK)