#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
//图节点
typedef struct AdjacentNodeType
{
int index;
struct AdjacentNodeType *nextNeighbor;
}AdjacentNode,*pAdjacentNode;
typedef struct VertexNode
{
int index;
char name;
int h;
int e;
pAdjacentNode current;
pAdjacentNode head;
struct VertexNode *next;
struct VertexNode *pre;
}Vertex,*pVertex;
//图
typedef struct
{
int vn;
int **E; //容量C作为边矩阵的值
pVertex *V;
int **f; //流值
int **rE; // 残留边
pVertex L; //前置重贴标签用到的链表,在initGraph()中初始化
}Graph,*pGraph;
void generateAdjacentList(pGraph g,int s,int t)
{
for(int i=0;i<g->vn;i++)
{
for(int j=0;j<g->vn;j++)
{
if(g->E[i][j]>0 || g->E[j][i]>0)
{
pAdjacentNode adj=(pAdjacentNode)malloc(sizeof(AdjacentNode));
adj->index=j;
adj->nextNeighbor=g->V[i]->head;
g->V[i]->head=adj;
}
}
}
}
//根据算法导论 图26-6初始化图
pGraph initGraph()
{
pGraph g=(pGraph)malloc(sizeof(Graph));
g->vn=6;
int s=0,t=g->vn-1;
pVertex vs=(pVertex)malloc(sizeof(Vertex));
vs->name='s';
vs->index=0;
pVertex v1=(pVertex)malloc(sizeof(Vertex));
v1->name='1';
v1->index=1;
pVertex v2=(pVertex)malloc(sizeof(Vertex));
v2->name='2';
v2->index=2;
pVertex v3=(pVertex)malloc(sizeof(Vertex));
v3->name='3';
v3->index=3;
pVertex v4=(pVertex)malloc(sizeof(Vertex));
v4->name='4';
v4->index=4;
pVertex vt=(pVertex)malloc(sizeof(Vertex));
vt->name='t';
vt->index=5;
g->V=(pVertex*)malloc(g->vn*sizeof(pVertex));
g->V[0]=vs;
g->V[1]=v1;
g->V[2]=v2;
g->V[3]=v3;
g->V[4]=v4;
g->V[5]=vt;
for(int i=0;i<g->vn;i++)
{
g->V[i]->current=g->V[i]->head=NULL;
g->V[i]->pre=g->V[i]->next=NULL;
}
g->L=NULL;
for(int i=g->vn-1;i>=0;i--)
{
if(i==s || i==t)
continue;
g->V[i]->next=g->L;
if(g->L)
g->L->pre=g->V[i];
g->L=g->V[i];
}
g->E = (int**)malloc(g->vn*sizeof(int*));
g->f= (int**)malloc(g->vn*sizeof(int*));
g->rE= (int**)malloc(g->vn*sizeof(int*));
for(int i=0;i<g->vn;i++)
{
g->E[i]=(int*)malloc(g->vn*sizeof(int));
g->f[i]=(int*)malloc(g->vn*sizeof(int));
g->rE[i]=(int*)malloc(g->vn*sizeof(int));
}
for(int i=0;i<g->vn;i++)
{
for(int j=0;j<g->vn;j++)
{
g->E[i][j]=0;
//g->f[i][j]=0;
}
}
g->E[0][1]=16;
g->E[0][2]=13;
g->E[1][3]=12;
g->E[2][1]=4;
g->E[2][4]=14;
g->E[3][2]=9;
g->E[3][5]=20;
g->E[4][3]=7;
g->E[4][5]=4;
generateAdjacentList(g,s,t);
return g;
}
void initResidualNetwork(pGraph g)
{
for(int i=0;i<g->vn;i++)
{
for(int j=0;j<g->vn;j++)
{
g->rE[i][j]=0;
}
}
for(int i=0;i<g->vn;i++)
{
for(int j=0;j<g->vn;j++)
{
if(g->E[i][j]>0)
{
int x=g->E[i][j]-g->f[i][j];
if(x>0)
g->rE[i][j]=x;
if(g->f[i][j]>0)
g->rE[j][i]=g->f[i][j];
}
}
}
}
void initializePreflow(pGraph g,int s)
{
for(int i=0;i<g->vn;i++)
{
g->V[i]->e=g->V[i]->h=0;
}
for(int i=0;i<g->vn;i++)
{
for(int j=0;j<g->vn;j++)
{
g->f[i][j]=0;
}
}
g->V[s]->h=g->vn;
for(int i=0;i<g->vn;i++)
{
if(i != s)
{
g->f[s][i]=g->E[s][i];
g->V[i]->e=g->E[s][i];
g->V[s]->e -= g->E[s][i];
}
}
}
void push(pGraph g,int u,int v)
{
if(g->V[u]->e<=0)
return;
if(g->V[u]->h != g->V[v]->h+1)
return;
if(g->rE[u][v]<=0)
return;
int d=g->V[u]->e < g->rE[u][v] ? g->V[u]->e : g->rE[u][v];
//更新流
if(g->E[u][v]>0)
{
g->f[u][v]+=d;
}
else
{
g->f[v][u]-=d;
}
//更新超额流
g->V[u]->e-=d;
g->V[v]->e+=d;
//更新残存图
if(g->E[u][v]>0)
{
int x=g->E[u][v]-g->f[u][v];
g->rE[u][v]=x;
if(g->f[u][v]>0)
g->rE[v][u]=g->f[u][v];
}
}
//进入函数时,默认保证g->V[u]->e>0
//返回能从u进行push的邻接顶点位置
//返回-1代表残留图中该顶点无邻接点
int relabel(pGraph g,int u)
{
int minh=INT_MAX,minPos;
for(int i=0;i<g->vn;i++)
{
if(i==u)
continue;
if(g->rE[u][i]>0)
{
if(g->V[i]->h<g->V[u]->h)
return i;
else
{
if(g->V[i]->h<minh)
{
minh=g->V[i]->h;
minPos=i;
}
}
}
}
if(minh<INT_MAX)
{
g->V[u]->h=minh+1;
return minPos;
}
else//u没有邻接点时走到这里
return -1;
}
void discharge(pGraph g,int u)
{
while(g->V[u]->e>0)
{
pAdjacentNode pv=g->V[u]->current;
if(pv==NULL)
{
relabel(g,u);
g->V[u]->current=g->V[u]->head;
}
else if(g->rE[u][pv->index]>0 && g->V[u]->h == g->V[pv->index]->h+1)
{
push(g,u,pv->index);
}
else
g->V[u]->current=pv->nextNeighbor;
}
}
void relabelToFront(pGraph g,int s,int t)
{
initializePreflow(g,s);
initResidualNetwork(g);
for(int i=0;i<g->vn;i++)
{
if(i==s || i==t)
continue;
g->V[i]->current=g->V[i]->head;
}
pVertex pu=g->L;
while(pu!=NULL)
{
int oldHeight=pu->h;
discharge(g,pu->index);
if(pu->h>oldHeight)
{
//链表中需要移动的节点是头节点则不移动
if(pu!=g->L)
{
pu->pre->next=pu->next;
if(pu->next)
pu->next->pre=pu->pre;
pu->next=g->L;
g->L->pre=pu;
pu->pre=NULL;
g->L=pu;
}
}
pu=pu->next;
}
}
void printFlow(pGraph g)
{
for(int i=0;i<g->vn;i++)
{
for(int j=0;j<g->vn;j++)
{
if(g->E[i][j]>0)
printf("%c->%c (%d/%d)\n",g->V[i]->name,g->V[j]->name,g->f[i][j],g->E[i][j]);
}
}
}
int calcuMaxFlow(pGraph g,int s)
{
int maxFlow=0;
for(int i=0;i<g->vn;i++)
{
if(i==s)
continue;
if(g->f[s][i]>0)
maxFlow+=g->f[s][i];
}
return maxFlow;
}
void main()
{
pGraph g=initGraph();
int s=0,t=g->vn-1;
relabelToFront(g,s,t);
int maxFlow=calcuMaxFlow(g,s);
printf("Max Flow is:%d\n",maxFlow);
printFlow(g);
getchar();
}