重标记与前移算法

来源:互联网 发布:js在新页面重定向url 编辑:程序博客网 时间:2024/04/29 19:45
#include <cstdio>
#include <list>
#include <algorithm>
using namespace std;
const int M = 10;
const int MAX = 0x7fffffff;
//const int NIL = -1;
int ver_amount;
int edge_amount;
int a[M][M];            //图的邻接矩阵
list<int> N[M];    //相邻表
list<int> L;            //包含V-{s,t}中所有顶点的链表L
int h[M];                    //高度
list<int>::iterator current[M];    //相邻表中当前位置,current[i]指向N[i]中当先被考察的节点
int e[M];                    //各顶点的余流
int f[M][M];            //流f
int C[M][M];            //记录各有向边的容量
                                            //Cf=C-f


/** 初始化前置流 **/
void Initialize_Preflow(int s)//初始化了h[M],e[M],f[M][M],C[M][M];
{
    int u,v;
    for(u=0;u<ver_amount;u++)
        for(v=0;v<ver_amount;v++)
        {
            if(a[u][v]!=MAX)
                C[u][v]=a[u][v];
            else
                C[u][v]=0;
        }
    for(u=0;u<ver_amount;u++)
    {
        h[u]=0;
        e[u]=0;
    }
    for(u=0;u<ver_amount;u++)
        for(v=0;v<ver_amount;v++)
        {
            f[u][v]=0;
            f[v][u]=0;
        }
    h[s]=ver_amount;
    for(u=0;u<ver_amount;u++)
    {
        if(a[s][u]!=MAX)
        {
            f[s][u]=C[s][u];
            f[u][s]=-C[s][u];
            e[u]=C[s][u];
            e[s]=e[s]-C[s][u];
        }
    }
}

/** 压入 **/
void Push(int u,int v)
{
    int df=min(e[u],C[u][v]-f[u][v]);
    f[u][v]=f[u][v]+df;
    f[v][u]=-f[u][v];
    e[u]=e[u]-df;
    e[v]=e[v]+df;
}

/** 重标记 **/
void Relabel(int u)
{
    int v,min=2*ver_amount-1;//高度函数的上界
    for(v=0;v<ver_amount;v++)
        if(C[u][v]-f[u][v]>0 && h[v]<min) //(u,v)要属于剩余网络
            min=h[v];
    h[u]=1+min;
}

/** 排除 **/
void Discharge(int u)    //传入顶点编号u,若顶点u溢出,则通过u的相邻表执行排除操作
{
    while(e[u]>0)
    {
        list<int>::iterator ite_v = current[u];
        if(ite_v==N[u].end())    //ite_v到N[u]底了
        {
            Relabel(u);
            current[u]=N[u].begin();
        }
        else if(C[u][*ite_v]-f[u][*ite_v]>0 && h[u]==h[*ite_v]+1)//满足压入条件
            Push(u,*ite_v);
        else
            current[u]++;
    }
}

/** 构建相邻表N[M] **/
void Build_N()
{
    int i,j;
    for(i=0;i<ver_amount-1;i++)
        for(j=i+1;j<ver_amount;j++)
        {
            if(a[i][j]!=MAX || a[j][i]!=MAX)//i,j之间可能会有残留边
            {
                N[i].push_back(j);
                N[j].push_back(i);
            }
        }
}

/** 建立链表L,把除源点和汇点以外的点加入L **/
void Build_L(int s,int t)
{
    int i;
    for(i=0;i<ver_amount;i++)
        if(i!=s&&i!=t)
            L.push_back(i);
}

/** 重标记与前移算法主函数 **/
void Relabel_To_Front(int s,int t)
{
    Initialize_Preflow(s);
    Build_N();//构建相邻表N[M];
    Build_L(s,t);//构建L;
    int i;
    for(i=0;i<ver_amount;i++)
        current[i]=N[i].begin();
    list<int>::iterator ite_L = L.begin();//链表L的遍历器
    while(ite_L!=L.end())
    {
        int u = *ite_L;
        int old_height = h[u];
        Discharge(u);
        if(h[u]>old_height)//如果u被重标记过,前移u;
        {
            L.erase(ite_L);
            L.push_front(u);
            ite_L=L.begin();
        }
        ite_L++;
    }   
}

int main()
{
    int i,u,v,w;
    scanf("%d%d",&ver_amount,&edge_amount);
    for(u=0;u<ver_amount;u++)
        for(v=0;v<ver_amount;v++)
            a[u][v]=MAX;
    for(i=0;i<edge_amount;i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        a[u][v]=w;
    }
    Relabel_To_Front(0,ver_amount-1);
    for(i=0;i<ver_amount;i++)
    {
        printf("Node %d\theight:%d    e[i]:%d\n",i,h[i],e[i]);
    }
    for(u=0;u<ver_amount;u++)
        for(v=0;v<ver_amount;v++)
        {
            if(a[u][v]!=MAX)
                printf("%d->%d:\t%d/%d\n",u,v,f[u][v],C[u][v]);
        }
    return 0;
}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 专卖店不给退怎么办 理发店顾客钱收少了怎么办 淘宝店铺搜不到怎么办 淘宝客服不在线怎么办 淘宝售后服务客服帮着卖家怎么办 老公一年找不到工作怎么办 淘宝店家跑了怎么办 淘宝卖家跑了怎么办啊 没发货退不了怎么办 微信上遇到诈骗怎么办 拼多多二级处罚怎么办 淘宝售后过了怎么办 遇到耍无赖的人怎么办 欠钱耍无赖得怎么办 借钱不还耍无赖怎么办 淘宝开食品店证件怎么办 手机卡掉了话费怎么办 手机变板砖怎么办 10086短信收不到怎么办 苹果手机成砖头怎么办 手机死砖了怎么办 苹果电脑成砖了怎么办 苹果误充游戏怎么办 话费如果交错了怎么办 联通充错号码怎么办 淘宝店铺假流量怎么办 空号交错话费怎么办 微信上被骗4800怎么办 移动手机号空号怎么办 微信充值充错号码对方是空号怎么办 买了运险费退货怎么办 手机玩吃鸡有点卡怎么办 微信手机充值充到空号怎么办 用微信交话费交错了怎么办 眼睫毛烫坏了怎么办 眼睫毛太硬了怎么办 微信话费充值空号怎么办 睫毛烫焦了怎么办 答题卡中间对折怎么办 充q币错误怎么办 睫毛烫坏了怎么办