/* maxflow.cpp */
#include <stdio.h>
#include "graph.h"
/*
special constants for node->parent
*/
#define TERMINAL ( (arc *) 1 ) /* to terminal */
#define ORPHAN ( (arc *) 2 ) /* orphan */
#define INFINITE_D ((int)(((unsigned)-1)/2)) /* infinite distance to the terminal */
/***********************************************************************/
/*
Functions for processing active list.
i->next points to the next node in the list
(or to i, if i is the last node in the list).
If i->next is NULL iff i is not in the list.
There are two queues. Active nodes are added
to the end of the second queue and read from
the front of the first queue. If the first queue
is empty, it is replaced by the second queue
(and the second queue becomes empty).
*/
template <typename captype, typename tcaptype, typename flowtype>
inline void Graph<captype,tcaptype,flowtype>::set_active(node *i)
{
if (!i->next)
{
/* it's not in the list yet */
if (queue_last[1]) queue_last[1] -> next = i;
else queue_first[1] = i;
queue_last[1] = i;
i -> next = i;
}
}
/*
Returns the next active node.
If it is connected to the sink, it stays in the list,
otherwise it is removed from the list
*/
template <typename captype, typename tcaptype, typename flowtype>
inline typename Graph<captype,tcaptype,flowtype>::node* Graph<captype,tcaptype,flowtype>::next_active()
{
node *i;
while ( 1 )
{
if (!(i=queue_first[0]))
{
queue_first[0] = i = queue_first[1];
queue_last[0] = queue_last[1];
queue_first[1] = NULL;
queue_last[1] = NULL;
if (!i) return NULL;
}
/* remove it from the active list */
if (i->next == i) queue_first[0] = queue_last[0] = NULL;
else queue_first[0] = i -> next;
i -> next = NULL;
/* a node in the list is active iff it has a parent */
if (i->parent) return i;
}
}
/***********************************************************************/
template <typename captype, typename tcaptype, typename flowtype>
inline void Graph<captype,tcaptype,flowtype>::set_orphan_front(node *i)
{
nodeptr *np;
i -> parent = ORPHAN;
np = nodeptr_block -> New();
np -> ptr = i;
np -> next = orphan_first;
orphan_first = np;
}
template <typename captype, typename tcaptype, typename flowtype>
inline void Graph<captype,tcaptype,flowtype>::set_orphan_rear(node *i)
{
nodeptr *np;
i -> parent = ORPHAN;
np = nodeptr_block -> New();
np -> ptr = i;
if (orphan_last) orphan_last -> next = np;
else orphan_first = np;
orphan_last = np;
np -> next = NULL;
}
/***********************************************************************/
template <typename captype, typename tcaptype, typename flowtype>
inline void Graph<captype,tcaptype,flowtype>::add_to_changed_list(node *i)
{
if (changed_list && !i->is_in_changed_list)
{
node_id* ptr = changed_list->New();
*ptr = (node_id)(i - nodes);
i->is_in_changed_list = true;
}
}
/***********************************************************************/
template <typename captype, typename tcaptype, typename flowtype>
void Graph<captype,tcaptype,flowtype>::maxflow_init()
{
node *i;
queue_first[0] = queue_last[0] = NULL;
queue_first[1] = queue_last[1] = NULL;
orphan_first = NULL;
TIME = 0;
for (i=nodes; i<node_last; i++)
{
i -> next = NULL;
i -> is_marked = 0;
i -> is_in_changed_list = 0;
i -> TS = TIME;
if (i->tr_cap > 0)
{
/* i is connected to the source */
i -> is_sink = 0;
i -> parent = TERMINAL;
set_active(i);
i -> DIST = 1;
}
else if (i->tr_cap < 0)
{
/* i is connected to the sink */
i -> is_sink = 1;
i -> parent = TERMINAL;
set_active(i);
i -> DIST = 1;
}
else
{
i -> parent = NULL;
}
}
}
template <typename captype, typename tcaptype, typename flowtype>
void Graph<captype,tcaptype,flowtype>::maxflow_reuse_trees_init()
{
node* i;
node* j;
node* queue = queue_first[1];
arc* a;
nodeptr* np;
queue_first[0] = queue_last[0] = NULL;
queue_first[1] = queue_last[1] = NULL;
orphan_first = orphan_last = NULL;
TIME ++;
while ((i=queue))
{
queue = i->next;
if (queue == i) queue = NULL;
i->next = NULL;
i->is_marked = 0;
set_active(i);
if (i->tr_cap == 0)
{
if (i->parent) set_orphan_rear(i);
continue;
}
if (i->tr_cap > 0)
{
if (!i->parent || i->is_sink)
{
i->is_sink = 0;
for (a=i->first; a; a=a->next)
{
j = a->head;
if (!j->is_marked)
{
if (j->parent == a->sister) set_orphan_rear(j);
if (j->parent && j->is_sink && a->r_cap > 0) set_active(j);
}
}
add_to_changed_list(i);
}
}
else
{
if (!i->parent || !i->is_sink)
{
i->is_sink = 1;
for (a=i->first; a; a=a->next)
{
j = a->head;
if (!j->is_marked)
{
if (j->parent == a->sister) set_orphan_rear(j);
if (j->parent && !j->is_sink && a->sister->r_cap > 0) set_active(j);
}
}
add_to_changed_list(i);
}
}
i->parent = TERMINAL;
i -> TS = TIME;
i -> DIST = 1;
}
//test_consistency();
/* adoption */
while ((np=orphan_first))
{
orphan_first = np -> next;
i = np -> ptr;
nodeptr_block -> Delete(np);
if (!orphan_first) orphan_last = NULL;
if (i->is_sink) process_sink_orphan(i);
else process_source_orphan(i);
}
/* adoption end */
//test_consistency();
}
template <typename captype, typename tcaptype, typename flowtype>
void Graph<captype,tcaptype,flowtype>::augment(arc *middle_arc)
{
node *i;
arc *a;
tcaptype bottleneck;
/* 1. Finding bottleneck capacity */
/* 1a - the source tree */
bottleneck = middle_arc -> r_cap;
for (i=middle_arc->sister->head; ; i=a->head)
{
a = i -> parent;
if (a == TERMINAL) break;
if (bottleneck > a->sister->r_cap) bottleneck = a -> sister -> r_cap;
}
if (bottleneck > i->tr_cap) bottleneck = i -> tr_cap;
/* 1b - the sink tree */
for (i=middle_arc->head; ; i=a->head)
{
a = i -> parent;
if (a == TERMINAL) break;
if (bottleneck > a->r_cap) bottleneck = a -> r_cap;
}
if (bottleneck > - i->tr_cap) bottleneck = - i -> tr_cap;
/* 2. Augmenting */
/* 2a - the source tree */
middle_arc -> sister -> r_cap += bottleneck;
middle_arc -> r_cap -= bottleneck;
for (i=middle_arc->sister->head; ; i=a->head)
{
a = i -> parent;
if (a == TERMINAL) break;
a -> r_cap += bottleneck;
a -> sister -> r_cap -= bottleneck;
if (!a->sister->r_cap)
{
set_orphan_front(i); // add i to the beginning of the adoption list
}
}
i -> tr_cap -= bottleneck;
if (!i->tr_cap)
{
set_orphan_front(i); // add i to the beginning of the adoption list
}
/* 2b - the sink tree */
for (i=middle_arc->head; ; i=a->head)
{
a = i -> parent;
if (a == TERMINAL) break;
a -> sister -> r_cap += bottleneck;
a -> r_cap -= bottleneck;
if (!a->r_cap)
{
set_orphan_front(i); // add i to the beginning of the adoption list
}
}
i -> tr_cap += bottleneck;
if (!i->tr_cap)
{
set_orphan_front(i); // add i to the beginning of the adoption list
}
flow += bottleneck;
}
/***********************************************************************/
template <typename captype, typename tcaptype, typename flowtype>
void Graph<captype,tcaptype,flowtype>::process_source_orphan(node *i)
{
node *j;
arc *a0, *a0_min = NULL, *a;
int d, d_min = INFINITE_D;
/* trying to find a new parent */
for (a0=i->first; a0; a0=a0->next)
if (a0->sister->r_cap)
{
j = a0 -> head;
if (!j->is_sink && (a=j->parent))
{
/* checking the origin of j */
d = 0;
while ( 1 )
{
if (j->TS == TIME)
{
d += j -> DIST;
break;
}
a = j -> parent;
d
Max-flow/min-cut工具箱Bk_matlab
5星 · 超过95%的资源 需积分: 50 110 浏览量
2015-01-29
19:19:42
上传
评论
收藏 26KB ZIP 举报
on2way
- 粉丝: 4130
- 资源: 10
最新资源
- Python大作业:音乐播放软件(爬虫+可视化+数据分析+数据库)
- 课程设计-python爬虫-爬取日报,爬取日报文章后存储到本地,附带源代码+课程设计报告
- 软件和信息技术服务行业投资与前景预测.pptx
- 课程设计-基于SpringBoot + Mybatis+python爬虫NBA球员数据爬取可视化+源代码+文档+sql+效果图
- 软件品质管理系列二项目策划规范.doc
- 基于TensorFlow+PyQt+GUI的酒店评论情感分析,支持分析本地数据文件和网络爬取数据分析+源代码+文档说明+安装教程
- 软件定义无线电中的模拟电路测试技术.pptx
- 软件开发协议(作为技术开发合同附件).doc
- 软件开发和咨询行业技术趋势分析.pptx
- 软件测试题详解及答案.doc
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈