算法导论 最大流 Push-Relabel

#include <stdio.h>  
#include <stdlib.h>  
#include <limits.h>  
  
//图节点    
typedef struct VertexNode    
{    
    char name;  
    int h;  
    int e;  
}Vertex,*pVertex;    
    
//图    
typedef struct     
{    
    int vn;    
    int **E;  //容量C作为边矩阵的值  
    pVertex *V;    
    int **f; //流值  
    int **rE; // 残留边  
}Graph,*pGraph;    
//根据算法导论 图26-6初始化图  
pGraph initGraph()    
{    
    pGraph g=(pGraph)malloc(sizeof(Graph));    
    g->vn=6;    
    pVertex vs=(pVertex)malloc(sizeof(Vertex));    
    vs->name='s';  
    pVertex v1=(pVertex)malloc(sizeof(Vertex));    
    v1->name='1';        
    pVertex v2=(pVertex)malloc(sizeof(Vertex));    
    v2->name='2';       
    pVertex v3=(pVertex)malloc(sizeof(Vertex));    
    v3->name='3';     
    pVertex v4=(pVertex)malloc(sizeof(Vertex));    
    v4->name='4';      
    pVertex vt=(pVertex)malloc(sizeof(Vertex));    
    vt->name='t';     
    
    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;  
    
    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;   
    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 printFlow2(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,%d,%d)->(%c,%d,%d) (%d/%d)\n",  
                g->V[i]->name,g->V[i]->h,g->V[i]->e,g->V[j]->name,g->V[j]->h,  
                g->V[j]->e,g->f[i][j],g->E[i][j]);  
        }  
    }  
    printf("\n");  
    for(int i=0;i<g->vn;i++)  
    {  
        for(int j=0;j<g->vn;j++)  
        {  
            if(g->rE[i][j]>0)  
                printf("%c->%c %d\n",g->V[i]->name,g->V[j]->name,g->rE[i][j]);  
        }  
    }  
}  
  
bool moreOperation(pGraph g,int s,int t)  
{  
    int x=-1;  
    for(int i=0;i<g->vn;i++)  
    {  
        if(i==s || i==t)  
            continue;  
        if(g->V[i]->e<=0)  
            continue;  
        //push之前,保证g->V[i]->e>0  
        x=relabel(g,i);  
        if(x>=0)  
        {  
            push(g,i,x);  
            return true;  
        }  
    }  
    return false;  
}  
  
void genericPushRelabel(pGraph g,int s,int t)  
{  
    initializePreflow(g,s);  
    initResidualNetwork(g);  
    int v=(s+1)%g->vn;  
    while(moreOperation(g,s,t))  
    {  
        //printFlow2(g);  
    };  
}  
  
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;
    genericPushRelabel(g,s,t);  
int maxFlow=calcuMaxFlow(g,s);
printf("Max Flow is:%d\n",maxFlow);
    printFlow(g);  
    getchar();  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值