Professional Documents
Culture Documents
Net w or k Flows
Imaginethatyouareacourierservice,andyouwanttodeliversomecargofromonecitytoanother.
Youcandeliverthemusingvariousflightsfromcitiestocities,buteachflighthasalimitedamountof
space that youcanuse. Animportantquestionis,howmuchof ourcargocanbeshippedtothe
destinationusingthedifferentflightsavailable?Toanswerthisquestion,weexplorewhatiscalleda
networkflowgraph,andshowhowwecanmodeldifferentproblemsusingsuchagraph.
AnetworkflowgraphG=(V,E)isadirectedgraphwithtwospecialvertices:thesourcevertexs,and
thesink(destination)vertext.Eachvertexrepresentsacitywherewecansendorreceivecargo.An
edge(u,v)inthegraphmeansthatthereisaflightthatfliesdirectlyfromutov.Eachedgehasan
associated capacity, always finite, representing the amount of space available on this flight. For
simplicity,weassumetherecanonlybeoneedge(u,v)forverticesuandv,butwedoallowreverse
edges(v,u).Firgure1isanexampleofanetworkflowgraphmodellingtheproblemstatedabove.
3
s
3
2
v
Figure1.Asimplecapacitiednetworkflowgraph.
Withthisgraph,wenowwanttoknowhowmuchcargowecanshipfromstot. Sincethecargo
"flows"throughthegraphfromstot,wecallthisthemaximumflowproblem. Astraightforward
solutionistodothefollowing:keepfindingpathsfromstotwherewecansendflowalong,sendas
muchflowaspossiblealongeachpath,andupdatetheflowgraphafterwardstoaccountfortheused
space.Thefollowingshowsanarbitraryselectionofapathontheabovegraph.
3, 3
s
3, 3
0, 2
0, 2
v
3, 4
Figure2.Thefirstnumberoneachedgeistheflow,andthesecondisthecapacity.
InFigure2,wepickedapaths u v t.Thecapacitiesalongthispathare3,3,4respectively,
whichmeanswehaveabottleneckcapacityof3wecansendatmost3unitsofflowalongthispath.
Nowwesend3unitsofflowalongthispath,andtrytoupdatethegraph.Howshouldwedothis?
Anobviouschoicewouldbetodecreasethecapacityofeachedgeusedby3wehaveusedup3
availablespacesalongeachedge,sothecapacityoneachedgemustdecreaseby3. Updatingthis
way,theonlyotherpathleftfromstotiss v t.Theedge(s,v)hascapacity2,andtheedge(v,t)
now has capacity 1, because of a flow of 3 from the last path. Hence, with the same update
procedure,weobtainFigure3below.
CPSC 490
3, 3
s
3, 3
0, 2
1, 2
v
4, 4
Figure3.Usingpaths v t.Algorithmends,butthisisnotoptimal.
Ouralgorithmnowends,becausewecannotfindanymorepathsfromstot(remember,anedgethat
hasnofreecapacitycannotbeused).However,canwedobetter?Itturnsoutwecan.Ifweonly
send2unitsofflow(u,v),anddivergethethirdunitto(u,t),thenweopenupanewspaceinboththe
edges(u,v)and(v,t).Wecannowsendonemoreunitofflowonthepaths v t,increasingour
totalflowto5,whichisobviouslythemaximumpossible.Theoptimalsolutionisthefollowing:
3, 3
s
2, 3
1, 2
2, 2
v
4, 4
Figure4.Optimalsolution.
So,whatiswrongwithouralgorithm?Oneproblemwasthatwepickedthepathsinthewrongorder.
Ifwehadpickedthepathss u tfirst,thenpicks u v t,thenfinallys vt,wewillendup
withtheoptimalsolution.Onesolutionistoalwayspicktherightorderingorpaths;butthiscanbe
difficult. Canweresolvethisproblemwithoutworryingaboutwhichpathswepickfirstandwhich
oneswepicklast?
Onesolutionisthefollowing.ComparingFigure3andFigure4,weseethatthedifferencebetween
thetwoareintheedges(s,v),(u,v)and(u,t).IntheoptimalsolutioninFigure4,(s,v)hasonemore
unitofflow,(u,v)hasonelessunit,and(u,t)hasonemoreunit.Ifwejustlookatthesethreeedges
andformapaths v u t,thenwecaninterpretthepathlikethis:wefirsttrytosendsomeflow
along(s,v),andtherearenomoreedgesgoingawayfromvthathasfreecapacity.Now,wecanpush
backflowalong(u,v),tellingothersthatsomeunitsofflowthatoriginallycamealong(u,v)cannow
betakenoverbyflowcomingintovalong(s,v).Afterwepushflowbacktou,wecanlookfornew
paths,andtheonlyedgewecanuseis(u,t).Thethreeedgeshaveabottleneckcapacityof1,dueto
theedge(s,v),andsowepushoneunitalong(s,v)and(u,t),butpushbackoneuniton(u,v).Think
ofpushingflowbackwardsasusingabackwardedgethathascapacityequaltotheflowonthatedge.
Itturnsoutthatthissmallfixyieldsacorrectsolutiontothemaximumflowproblem.Westatethe
algorithmformallyhere.Wefirstassociateaflowfunctionalongeachedgef(u,v),thattellsushow
manyunitsofflowgofromutov.Obviously,f(u,v)capacity(u,v),andweinitiallysetf(u,v)to0
foralledges.Now,wekeepfindingpathsfromstot,usingonlytwotypesofedges.First,wecanuse
anyedge(u,v)thathasf(u,v)<capacity(u,v)[aforwardedge],andsecond,wecanuseanyedge
(v,u)togobackwardfromutoviff(v,u)>0[abackwardedge].Ifbothoptionsexist,wecanpick
anyoneofthem(althoughpickingbackwardedgesoverforwardedgeswouldavoidalotoftroubles
lateron).Thealgorithmendswhennomorepathsarefound.
CPSC 490
Thenextstepistosendflowalongthispath.Wefirstneedtocalculatethebottleneckcapacity.For
forwardedges,thisamountisjustcapacity(u,v)f(u,v)thespacesremaining. But,for backward
edges,thisamountisf(v,u)theamountofflowthatwecanpushback.Oncewehavethebottleneck
capacity(theminimumalongthepath),wethensendthismuchflowalongthepath,andupdatethe
graph. Whenupdatingthegraph,wesimplyincreaseflowonforwardedges,anddecreaseflowon
backwardedges.Hereisourimplementation.
Example1.ImplementationofMaximumFlow.
intfordFulkerson(intn,ints,intt)
{//ASSUMES:cap[u][v]storescapacityofedge(u,v).cap[u][v]=0fornoedge.
//Initializetheflownetworksothatfnet[u][v]=0forallu,v
intflow=0;//noflowyet
while(true){
//Findanaugmentingpath,usingBFS
for(inti=0;i<n;i++)prev[i]=1;
queue<int>q;
prev[s]=2;
q.push(s);
while(!q.empty()&&prev[t]==1){
intu=q.front();
q.pop();
for(intv=0;v<n;v++){
if(prev[v]==1){//notseenyet
if(fnet[v][u]||fnet[u][v]<cap[u][v]){
//eitherabackwardedge(v,u)oraforwardedge(u,v)
prev[v]=u;
q.push(v);
}
}
}
}
//Seeifwecouldn'tfindanypathtot(thasnoparents)
if(prev[t]==1)break;
//Getthebottleneckcapacity
intbot=INT_MAX;
for(intv=t,u=prev[v];u>=0;v=u,u=prev[v]){
if(fnet[v][u])//alwaysusebackwardedgeoverforward
bot=min(bot,fnet[v][u]);
else//mustbeaforwardedgeotherwise
bot=min(bot,cap[u][v]fnet[u][v]);
}
//updatetheflownetwork
for(intv=t,u=prev[v];u>=0;v=u,u=prev[v]){
if(fnet[v][u])//backwardedge>subtract
fnet[v][u]=bot;
else//forwardedge>add
fnet[u][v]+=bot;
}
//Sent'bot'amountofflowfromstot,soupdateflow
flow+=bot;
}
returnflow;
}
CPSC 490
There are several things to note in the implementation above. We are using a BFS to find an
augmentingpathineachstep.Wesetprev[s]=2,sothatitisconsideredseen(notseenis=1),
anditsparentisnotavertex. Weusethisintheloopsbelowtocheckforbottleneckcapacityby
repeatedlypickingedges(u,v)inthepathaslongasuisavalidvertex.Also,noticethatprev[]does
nottellyouwhetheraforwardorbackwardedgeischosen.Itdoesn'tmatter,becauseinbothcases
wearegoingfromutov. However,whencalculatingthebottleneckcapacity,weassumethatifa
backwardedgeexists,thenwewillalwaysuseitoveraforwardedge.Thisavoidstheproblemofflow
goinginbothdirectionsbetweenvertices(whyisthistrue?).
Thissumsupouralgorithm.ThisalgorithmisfrequentlycalledtheFordFulkersonAlgorithmafterits
discoverers.Now,howdoweknowthatitworks?Wehavetoprovetwothings:1)thatthealgorithm
terminatesafterafinitenumberofcomputations,and2)thatthealgorithm outputsthemaximum
flowwhenitterminates.Theproofofcorrectnessisdifficult,andisprovedwiththemuchcelebrated
MaxflowMincutTheoremthatcanbefoundintheBigWhitebook(Cormenetal.,Introductionto
Algorithms)andcoveredinCS420,hencewewillnotdiscussithere.However,wewillprovethat
thealgorithmalwaysterminates.
ProofofTerminationoftheFordFulkersonAlgorithm.
Whenwefindapathfromstot,wecanonlyuseforwardedgesandbackwardedges.Sinceweare
findingapath,wenevervisitavertextwice.Sinceeachpathgoesfromstot,wewillneverfinda
backwardedgefroms,orabackwardedgetotiftheyexist,thenwehaveflowcomingintosorflow
comingoutoft,bothimpossiblewhenallourpathsgofromstot.Therefore,eachpathwillaugment
theflowofthegraphbyatleastoneunit,becauseboththefirstandlastedgeusedinthepathare
forward edges. Since each capacity is finite, the algorithm can only find a finite number of
augmentingpaths,andthusmustendinafinitenumberofiterations.
Timecomplexity
TherunningtimeoftheFordFulkersonalgorithmisO((n+m)*F),wheremisthenumberofedges,
andFisthemaximumflowinthegraph.ThisisbecausewecandoatmostFaugmentingpaths,each
beingaBFS,andsoneedsO(n+m)time(OurimplementationofBFSaboveisonly O n2 becauseit
usesanadjacencymatrix).However,EdmondsandKarpprovedthatifwealwaysfindtheshortest
augmentingpath,thenwecanachieveabetterbound.SinceBFSalreadyfindstheshortestpathinan
unweightedgraph,theimplementationaboveisalreadytheEdmondsKarpalgorithm. Thisrunsin
2
3
O m n timewithanadjacencylistand O m n withanadjacencymatrix,asabove,becausein
this case BFS takes quadratic time. There are better, more complicated algorithms that solve the
maximumflowproblemin O m n 2 andeven O n 3 time.Descriptionsofthesealgorithmsanda
proofofthe O m 2 n runningtimeboundfortheEdmondsKarpalgorithmcanbefoundintheBig
Whitebook.
AdditionalApplicationsofMaximumFlow
Many problems in the real world or in mathematics lend themselves readily to be solved using
maximumflow."Real"networks,liketheInternetorelectroniccircuitboards,aregoodexamplesof
flow networks (badwidths as capacities). Many transportation problems are also maximum flow
problems.Inthenextsectionwewilldiscussonecommonapplicationofmaximumflowmatching.
Bipartit e matchi n g
Abipartite(orbicolourable)graphisagraphG=(V,E)inwhichitispossibletosplitthesetofvertices,
V,intotwononemptysetsLandRsuchthatalloftheedgesinEhaveoneendpointinLandthe
CPSC 490
otheroneinR.Amatchinginanygraphisanysubset,S,oftheedgeschoseninsuchawaythatno
twoedgesinSshareanendpoint.Amaximummatchingisamatchingofmaximumsize.Theproblem
offindingamaximummatchinginagivengraphisNPhardingeneral,butifthegraphisbipartite,
thereisaneatpolynomialtimesolution.
Firstofall, why dowecareabout bipartitematching?Hereisaclassicproblem. Therearemjob
applicantsandnjobopenings.Eachapplicanthasasubsetofthejobopeningssheisinterestedin.
Conversely,eachjobopeningcanonlyacceptoneapplicantoutofsomesubsetoftheapplicants.In
other words, there are certain allowed or "compatible" pairings of applicants to jobs. Find an
assignmentofjobstoapplicantsinsuchawayallthepairingsareallowedandasmanyapplicantsas
possiblegetjobs.
Wecanmodelthiswithabipartitegraphontheleftsidewehavetheapplicantsandontheright
sidewehavethejobs.Drawanedgebetweenapplicantuandjobviftheyarecompatible.Theanswer
thatwearelookingforisthemaximummatching.
OnewaytosolvetheproblemistoreduceittoaninstanceofMaximumFlow.Drawthebipartite
graphwithapplicantsontheleftandjobsontheright.Giveeachedgeacapacityof1havingaflow
of1betweenapplicantuandjobvwillcorrespondtomatchingapplicantutojobv.Nowweneedto
ensurethatnoapplicantgetsmatchedtomorethan1job.Forthat,addavertex,s,onthefarleftand
connectiteachapplicantbyanedgeofcapacity1.Wealsowanteachjobtoonlybefilledbyatmost
oneapplicant.Toenforcethat,addavertex,t,onthefarrightandconnecteachjobopeningtotbyan
edgeofcapacity1.Finally,findthemaximumflowfromstot.Theamountofflowwecanpushis
exactlythenumberoforiginaledgesthatwillbeusedtoconnectanapplicanttoajob.Furthermore,
noapplicantorjobvertexwillbeusedmorethanonce.Togettheoptimalmatching,readitofffrom
theresultingflownetwork.
The implementation of this algorithm is straightforward once we have the code for MaxFlow.
However,sinceeachedgehascapacity1,wecansimplifythecodealot.Hereisanimplementation
thatusesDFStofindaugmentingpathsintheFordFulkersonalgorithmandrepresentsthegraphand
theflownetworkimplicitly.
Example1:MaximumBipartiteMatching
//defineMandNtobethemaximumsizesoftheleftandrightsetrespectively
boolgraph[M][N];
boolseen[N];
intmatchL[M],matchR[N];
intm,n;
boolbpm(intu){
for(intv=0;v<n;v++)if(graph[u][v]){
if(seen[v])continue;
seen[v]=true;
if(matchR[v]<0||bpm(matchR[v])){
matchL[u]=v;
matchR[v]=u;
returntrue;
}
}
returnfalse;
}
intmain(){
//Readinputandpopulategraph[][]
//SetmtobethesizeofL,ntobethesizeofR
CPSC 490
memset(matchL,1,sizeof(matchL));
memset(matchR,1,sizeof(matchR));
intcnt=0;
for(inti=0;i<m;i++)
{
memset(seen,0,sizeof(seen));
if(bpm(i))cnt++;
}
//cntcontainsthesizeofthematching
//matchL[i]iswhatleftvertexiismatchedto(or1ifunmatched)
//matchR[j]iswhatrightvertexjismatchedto(or1ifunmatched)
return0;
}
Thecodeissurprisinglyshort,comparedtothemaximumflowcode,andmostoftheworkisdoneby
thebpm(u)functionthattriestomatchtheleftvertexutosomethingontherightside.Itdoesthatby
tryingallrightverticesvandassigningutovifeithervisunassigned,orifv'smatchontheleftside
can be reassigned to some other vertex on the right that is larger than v. If you try running this
algorithmonanexample,youwillseethatthisissimplyanotherwayofimplementingDFS.Eachcall
tobpm(u)findsanaugmentingpathstartingatu.Thepathisallowedtouselefttorightedgesthat
arestillunused,aswellasrighttoleftedgesthatareused(byundoingaunitofflow).bpm(u)returns
true if a path was found and false otherwise. Each augmenting path adds one more edge to the
matching,andthesearecountedbythe'cnt'variableinmain().Theseen[]arrayistheusualDFSseen
[]array.matchL[]andmatchR[]storethematching;a1means"vertexisnotmatched(yet)".
Can you determine the worstcase running time of this algorithm? (Typing the link below in the
browser and reading it there would be cheating.) Note that the bipartite matching problem is
symmetric.Wecanfliptheleftandrightsidesofthegraphandassignjobstoapplicantsinsteadof
applicantstojobsit'sthesamething.Usingthisfact,canyouimprovetheworstcaserunningtime?
Howcouldyoudothatwiththefewestchangestothecode?
Thiscode,withalotmorecommentscanbefoundhere:
http://www.lexansoft.com:8081/tools/bpm.cpp
Andhereisanimplementationofmaximumflow:
http://www.lexansoft.com:8081/tools/flow.cpp
References
Cormen,ThomasH.,etal.IntroductiontoAlgorithms.,2nded.Cambridge:TheMITpress,2002.