重标记与前移算法
来源:互联网 发布: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;
}
#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;
}
- 重标记与前移算法
- 最大流:压入与重标记算法
- 压入与重标记算法(预流推进算法)
- 最大流算法之-增广路径(path augmentation)and压入与重标记算法(push-relable)
- H3C-QoS实例六:优先级重标记与队列调度
- 算法与数据结构前绪
- unix重定向标记
- 时间复杂度标记与分析(算法分析与设计)
- 数据结构与算法(Python)-前篇
- 加法模型与前向分布算法
- (一)数据结构与算法--前篇
- 二值图像连通域标记算法与代码
- 二值图像连通域标记算法与代码
- 区域标记-8连通与4连通算法
- 二值图像连通域标记算法与代码
- 二值图像连通域标记算法与代码
- 二值图像连通域标记算法与代码
- 二值图像连通域标记算法与代码
- 关于调用约定和extern “C”对程序设计的作用
- C/C++/C#面试题精选(2)
- UVa 11636 Hello World! (数学)
- 湘潭邀请赛A
- python第三方库推荐 - 优雅的数据验证库schema
- 重标记与前移算法
- 关于SVN Hooks(钩子)的使用
- ListView Tips & Tricks
- android4.2 蓝牙 bluetooth 第2节: 打开蓝牙
- vim vimrc
- 博客介绍
- LeetCode 53: Maximum Subarray
- android4.2-- 蓝牙 bluetooth第3节:搜索蓝牙
- 找工作