[Drainage Ditches]USACO

最大流问题,这题提交了提交了两次,第一次提交时test9输出错误,查了半天才发现数据中有重复的边。仔细看了一下题“ Note however, that there can be more than one ditch between two intersections.”也就是说,两个点之间可以有多条边。把多条边合成一条边就OK了。

用的是relabel to front.  为了方便,代码全部用的数组。

--------------------------------------------

/*
ID: zhangyc1
LANG: C++
TASK: ditch
*/
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;

#define MAX_HEIGHT 1000000
ofstream fileout("ditch.out");
const int NODENUM = 201;
int N, M;
int arrExtra[NODENUM]; // 预流
int arrCap[NODENUM][NODENUM], arrFlow[NODENUM][NODENUM]; // 容量,当前流量
int arrVisitList[NODENUM], arrHeight[NODENUM], arrVisitPos[NODENUM]; // 节点的处理顺序,节点高度,节点的访问指针

void prepairData()
{
    memset(arrCap, 0, sizeof(arrCap));
    memset(arrFlow, 0, sizeof(arrFlow));
    memset(arrExtra, 0, sizeof(arrExtra));
    memset(arrHeight, 0, sizeof(arrHeight));

    ifstream filein("ditch.in");
    filein >> N >> M;
    arrHeight[1] = M;

    int nFrom, nTo, nCap;
    for (int i = 0; i < N; i++)
    {
        filein >> nFrom >> nTo >> nCap;

        // 两个点之前可能有多条沟
        arrCap[nFrom][nTo] += nCap;
    }
    for (int i = 0; i < M - 2; i++)
        // 设为{2, 3, 4 ... M-1}
    {
        arrVisitList[i] = i + 2;
    }
    for (int i = 0; i <= M; i++)
        // 从源点开始
    {
        arrVisitPos[i] = 1;
    }
    for (int i = 2; i <= M; i++)
    {
        arrFlow[1][i] = arrCap[1][i];
        arrFlow[i][1] = -arrFlow[1][i];
        arrExtra[i] += arrCap[1][i];
        arrExtra[1] -= arrCap[1][i];
    }
    filein.close();
}

void PushOperation(int u, int v)
{
    int nMin = min(arrExtra[u], arrCap[u][v] - arrFlow[u][v]);
    arrExtra[u] -= nMin; arrExtra[v] += nMin;
    arrFlow[u][v] += nMin; arrFlow[v][u] = -arrFlow[u][v];
}

void RelabelOperation(int u)
{
    int nMin = MAX_HEIGHT;
    for (int v = 1; v <= M; v++)
    {
        if (arrCap[u][v] > arrFlow[u][v] && nMin > arrHeight[v])
            nMin = arrHeight[v];
    }
    arrHeight[u] = nMin + 1;
}

void Dicharge(int u)
{
    while(arrExtra[u] > 0)
    {
        if (arrVisitPos[u] <= M)
        {
            if (arrHeight[u] > arrHeight[arrVisitPos[u]] && arrCap[u][arrVisitPos[u]] > arrFlow[u][arrVisitPos[u]])
            {
                PushOperation(u, arrVisitPos[u]);
            }
            else
                arrVisitPos[u]++;
        }
        else
        {
            RelabelOperation(u);
            arrVisitPos[u] = 1;
        }
    }
}

void MoveToFront(int u)
{
    int nKey = arrVisitList[u];
    for (int i = u; i > 0; i--)
    {
        arrVisitList[i] = arrVisitList[i - 1];
    }
    arrVisitList[0] = nKey;
}

void RelabelToFront()
{
    int nCurVisit = 0;
    while (nCurVisit < M - 2)
    {
        int u = arrVisitList[nCurVisit];
        int oldHeight  = arrHeight[u];
        Dicharge(u);
        if (oldHeight != arrHeight[u])
        {
            MoveToFront(nCurVisit);
            nCurVisit = 1;
        }
        else
            nCurVisit++;
    }
}

int main(){
    prepairData();
    RelabelToFront();
    // should be 2763609
    fileout << arrExtra[M] << endl;
    fileout.close();    
    return 0;
}

 

posted @ 2013-03-15 14:04  J.Z's World  阅读(213)  评论(0编辑  收藏  举报