# 网络流---预流推进(转帖)

int MAXFLOW()
{
hights();
prepare();
while (!Q.empty()) {
u = Q.get;
for each e in G ' (from u) push(e);
if (!fixed(u)) reCalc(u);
}
}


(1).选出Q的一个活动顶点u。并依次判断残量网络G'中每条边(u, v)，若h(u) = h(v) + 1，则顺着这里条边推流，直到Q变成非活动结点（不存在多余流量）。(Push推流过程)
(2).如果u还是活动结点。则需要对u进行重新标号：h(u) = min{h(v) + 1}，其中边(u,v)存在于G' 中。然后再将u加入队列。(reCalc过程)

const int size = 501;
const int MAX = 1 << 15;

int graph[size][size];
int label[size];		//标号
bool visited[size];

bool bfs(int st, int ed)
{
memset(label, -1, sizeof(label));
memset(visited, false, sizeof(visited));
label[st] = 0;
visited[st] = true;
vector < int >plist;
plist.push_back(st);
while (plist.size()) {
int p = plist[0];
plist.erase(plist.begin());
for (int i = 0; i < size; i++) {
if (graph[i][p] > 0 && !visited[i]) {
plist.push_back(i);
visited[i] = true;
label[i] = label[p] + 1;
}
}
}
if (label[ed] == -1) {
return false;
}
return true;
}

int inflow[size];		//流入量

int maxFlow()
{
memset(inflow, 0, sizeof(inflow));

//hights
bfs(size - 1, 0);		//end point: size - 1, start point: 0
memset(visited, false, sizeof(visited));

//prepare()
vector < int >plist;
for (int i = 0; i < size; i++) {
if (graph[start][i] > 0) {
inflow[i] = graph[start][i];
graph[start][i] -= inflow[i];
graph[i][start] += inflow[i];
if (!visited[i]) {
plist.push_back(i);
visited[i] = true;
}
}
}
while (plist.size()) {
int p = plist[0];
plist.erase(plist.begin());
visited[p] = false;
int minLabel = -1;
for (int i = 0; i < size; i++) {
if (graph[p][i] > 0) {
if (label[p] == label[i] + 1) {
int flow = min(inflow[p], graph[p][i]);
inflow[p] -= flow;
inflow[i] += flow;
graph[p][i] -= flow;
graph[i][p] += flow;

if (!visited[i] && inflow[i] > 0) {
plist.push_back(i);
visited[i] = true;
}
}
}
}
if (inflow[p] > 0 && p != end) {
for (int i = 0; i < size; i++) {
if (graph[p][i] > 0) {
if (minLabel == -1 || minLabel > label[i] + 1) {
minLabel = label[i] + 1;
}
}
}
if (!visited[p] && minLabel != -1 && minLabel < size)	//minLabel < size, 这个条件需要加上, 因为经过测试发现有死循环的可能
{
for (int i = 0; i < size; i++) {
if (label[i] + 1 == minLabel && graph[p][i] > 0) {
visited[p] = true;
label[p] = minLabel;
plist.push_back(p);
break;
}
}
}
}
}
return inflow[end];
}


posted @ 2010-08-03 08:17  open source  阅读(1827)  评论(3编辑  收藏