POJ1459 最高标号预留推进算法

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <queue>
using std::queue;
#define Max 65535
int V, V_Source, V_End, E;
int SuperSource, SuperEnd, level;
int h[103], e[103];
int list[103][103], f[103][103], Map[103][103];
void bfs()
{
    bool visit[103];
    queue<int> queue_vertex;
    int x;
    memset(h, 0, sizeof(h));
    memset(visit, false, sizeof(visit));
    queue_vertex.push(SuperEnd);
    visit[SuperEnd] = true;
    while (!queue_vertex.empty())
    {
        x = queue_vertex.front();
        queue_vertex.pop();
        for (int i = 0; i < V; ++i)
            if (!visit[i] && Map[i][x] > 0)
            {
                queue_vertex.push(i);
                visit[i]=true;
                h[i] = h[x] + 1;
            }
    }
    h[SuperSource] = V - 1;
}
void init()
{
    char str[101];
    memset(f, 0, sizeof(f));
    memset(e, 0, sizeof(e));
    memset(Map, 0, sizeof(Map));
    memset(list, 0, sizeof(list));
    SuperSource = V++;
    SuperEnd = V++;
    for (int i = 0, x, y, z; i < E; Map[x][y] = z, ++i)
        scanf("%d %d %d", &x, &y, &z);
    for (int i = 0, x, z; i < V_Source; Map[SuperSource][x] = z, ++i)
        scanf("%d %d", &x, &z);
    for (int i = 0, x, z; i < V_End; Map[x][SuperEnd] = z, ++i)
        scanf("%d %d", &x, &z);
    bfs();
    for (int i = 0; i < V; ++i)
        if (Map[SuperSource][i] > 0)
        {
            e[SuperSource] -= Map[SuperSource][i];
            e[i] += Map[SuperSource][i];
            f[SuperSource][i] += Map[SuperSource][i];
            f[i][SuperSource] = -f[SuperSource][i];             
        }
    for (int i = 0, j = V - 2, x; i < j; ++i)
        if (e[i] > 0)
        {
            ++list[h[i]][0];
            x = list[h[i]][0];
            list[h[i]][x] = i;
        }
}
void push(int u, int v)
{
    int tem = std::min(e[u], Map[u][v] - f[u][v]), x;
    if (e[v] == 0 && v != SuperSource && v != SuperEnd)
    {
        ++list[h[v]][0];
        x = list[h[v]][0];
        list[h[v]][x] = v;
        if (h[v] > level)
            level = h[v];           
    }
    e[u] -= tem;
    e[v] += tem;
    f[u][v] += tem;
    f[v][u] = -f[u][v];     
}
void relabel(int v)
{
    int mh = Max;
    for (int i = 0; i < V; ++i)
        if (i != v && h[i] >= h[v] && Map[v][i] - f[v][i] > 0)
            mh = std::min(mh, h[i]);
    h[v] = mh + 1;
    level = h[v];
    ++list[level][0];
    list[level][1] = v; 
}
void work()
{
    int v, tem, flag;
    level = 0;
    for (int i = 0, j = V - 2; i < j; ++i)
        if (e[i] > 0)
            level = std::max(level, h[i]);
    while (level)
    {
        tem = list[level][0];
        v = list[level][tem];
        --list[level][0];
        while (level > 0 && list[level][0] == 0)
            --level;
        flag = false;
        for (int i = 0; i < V; ++i)
        {
            if (e[v] == 0)
                break;
            if (h[i] + 1 == h[v] && Map[v][i] - f[v][i] > 0)
            {
                push(v, i);
                flag = true;
            }
        }
        if (!flag || e[v] > 0)
            relabel(v);
    }
}
int main()
{
    while (scanf("%d %d %d %d", &V, &V_Source, &V_End, &E)!= EOF)
    {
        init();
        work();
        printf("%d\n", e[SuperEnd]);
    }
    return 0;
}

额...原题里面说有一堆出发点, 一堆接收点, 一堆中转站, 还是标准方法: 建立超级原点和超级汇点, 然后执行即可.

嗯...用的是最高标号预留推进算法, 算是网络流里面比较快速的算法了, 复杂度是n*n*√m, 还是相当迅速的

参照了图论书上的代码写了写...但是感觉还是不太好

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值