33,009
社区成员
发帖
与我相关
我的任务
分享
#include <iostream>
#include <queue>
using namespace std;
//Relabel()函数内用
#define MAX 100000
//包括源点(0),汇点(5),所有点在内,一共6个点,算法导论405页的图.
const int numV=6;
//记录是否在队列内(具有余流的点(溢出点))
bool inQueue[numV];
//顶点的高度h[]
int h[numV];
//顶点的余流e[],e[]>0表示溢出
int e[numV];
//流网络
struct
{
int c; //容量
int f; //流
}flowNet[numV][numV];
//initializePreFlow(queue<int> &)
void initializePreFlow(queue<int> &eQ)
{
//初始化高度与余流,清理队列标记
for(int i=0;i<numV;++i)
{
h[i]=0;
e[i]=0;
inQueue[i]=false;
}
//处理源s的高度
h[0]=numV;
//初始化前置流
for(int i=1;i<numV;++i)
{
flowNet[0][i].f+=flowNet[0][i].c;
flowNet[i][0].f-=flowNet[0][i].c;
e[0]-=flowNet[0][i].c;
e[i]+=flowNet[0][i].c;
if(e[i]>0&&i!=5) //进入队列的必须是e[]>0的,而且不能是汇点***********
{
eQ.push(i);
inQueue[i]=true;
}
}
}
//relabel() 重标记
void relabel(int u)
{
int minH=MAX;
for(int i=0;i<numV;++i)
{
if((flowNet[u][i].c-flowNet[u][i].f)>0&&h[i]<minH)
{
minH=h[i];
}
}
h[u]=1+minH;
}
//push()
void push(int u,int v)
{
int dFlow=e[u]<(flowNet[u][v].c-flowNet[u][v].f) ? e[u]:(flowNet[u][v].c-flowNet[u][v].f);
flowNet[u][v].f+=dFlow;
flowNet[v][u].f-=dFlow;
e[u]-=dFlow;
e[v]+=dFlow;
}
//genericPushRelabel() 实现压入重标记算法
int genericPushRelabel()
{
queue<int> eQ;
initializePreFlow(eQ);
int u,v;
int sum=0;
while(!eQ.empty())
{
u=eQ.front();
//寻找可以压入的边(u,v)
for(v=0;v<numV;++v)
{
if((flowNet[u][v].c-flowNet[u][v].f)>0&&(h[u]==h[v]+1))
{
break;
}
}
//如果找到可以压入的边
if(v!=numV)
{
push(u,v); //压入流
if(0==e[u])//如果u没有余流,则成为死结点
{
inQueue[u]=false;
eQ.pop();
}
if(inQueue[v]==false&&e[v]>0) //如果v不在队列内,且余流>0 **********
{
if(v!=5&&v!=0) //非源非终,因为源与终都不是溢出点
{
inQueue[v]=true;
eQ.push(v);
}
}
}
//没有可以压入的边,根据引理26.15,u肯定可以重标记
else
{
relabel(u);
}
}
return e[5]; //返回汇点t的余流就可以了
}
int main()
{
for(int i=0;i<numV;++i)
{
for(int j=0;j<numV;++j)
{
cin>>flowNet[i][j].c; //有边为实际容量,无边为0,flowNet(u,u)=0
flowNet[i][j].f=0;
}
}
cout<<genericPushRelabel()<<endl;
return 0;
}
[code=C/C++]#include <iostream>
#include <queue>
using namespace std;
//Relabel()函数内用
#define MAX 100000
//包括源点(0),汇点(5),所有点在内,一共6个点,算法导论405页的图.
const int numV=6;
//记录是否在队列内(具有余流的点(溢出点))
bool inQueue[numV];
//顶点的高度h[]
int h[numV];
//顶点的余流e[],e[]>0表示溢出
int e[numV];
//流网络
struct
{
int c; //容量
int f; //流
}flowNet[numV][numV];
//initializePreFlow(queue<int> &)
void initializePreFlow(queue<int> &eQ)
{
//初始化高度与余流,清理队列标记
for(int i=0;i<numV;++i)
{
h[i]=0;
e[i]=0;
inQueue[i]=false;
}
//处理源s的高度
h[0]=numV;
//初始化前置流
for(int i=1;i<numV;++i)
{
flowNet[0][i].f+=flowNet[0][i].c;
flowNet[i][0].f-=flowNet[0][i].c;
e[0]-=flowNet[0][i].c;
e[i]+=flowNet[0][i].c;
if(e[i]>0)
{
eQ.push(i);
inQueue[i]=true;
}
}
}
//relabel() 重标记
void relabel(int u)
{
int minH=MAX;
for(int i=0;i<numV;++i)
{
if((flowNet[u][i].c-flowNet[u][i].f)>0&&h[i]<minH)
{
minH=h[i];
}
}
h[u]=1+minH;
}
//push()
void push(int u,int v)
{
int dFlow=e[u]<(flowNet[u][v].c-flowNet[u][v].f) ? e[u]:(flowNet[u][v].c-flowNet[u][v].f);
flowNet[u][v].f+=dFlow;
flowNet[v][u].f-=dFlow;
e[u]-=dFlow;
e[v]+=dFlow;
}
//genericPushRelabel() 实现压入重标记算法
int genericPushRelabel()
{
queue<int> eQ;
initializePreFlow(eQ);
int u,v;
int sum=0;
while(!eQ.empty())
{
u=eQ.front();
//寻找可以压入的边(u,v)
for(v=0;v<numV;++v)
{
if((flowNet[u][v].c-flowNet[u][v].f)>0&&(h[u]==h[v]+1))
{
break;
}
}
//如果找到可以压入的边
if(v!=numV)
{
push(u,v); //压入流
if(0==e[u])//如果u没有余流,则成为死结点
{
inQueue[u]=false;
eQ.pop();
}
if(inQueue[v]==false&&e[v]!=0) //如果v不在队列内,且余流!=0
{
if(v!=5&&v!=0) //非源非终,因为源与终都不是溢出点
{
inQueue[v]=true;
eQ.push(v);
}
}
}
//没有可以压入的边,根据引理26.15,u肯定可以重标记
else
{
relabel(u);
}
}
return e[5]; //返回汇点t的余流就可以了
}
int main()
{
for(int i=0;i<numV;++i)
{
for(int j=0;j<numV;++j)
{
cin>>flowNet[i][j].c; //有边为实际容量,无边为0,flowNet(u,u)=0
flowNet[i][j].f=0;
}
}
cout<<genericPushRelabel()<<endl;
return 0;
}
#include <iostream>
#include <queue>
using namespace std;
//BFS()用
#define MAX 100000
//包括源点(0),汇点(5),所有点在内,一共6个点,算法导论405页的图.
const int numV=6;
//广搜记录是否已访问
bool visited[numV];
//流网络
struct
{
int c; //容量
int f; //流
}flowNet[numV][numV];
//广搜Info
struct
{
int v; //前驱结点号
int minF; //路径上最小残留
}pre[numV];
//BFS()
bool BFS()
{
queue<int> Q;
Q.push(0);
visited[0]=true;
int unDead;
while(!Q.empty())
{
unDead=Q.front();
Q.pop();
for(int i=0;i<numV;++i)
{
if(visited[i]==false&&i!=unDead&&(flowNet[unDead][i].c-flowNet[unDead][i].f)>0)
{
visited[i]=true;
Q.push(i);
pre[i].v=unDead;
pre[i].minF=( pre[unDead].minF > (flowNet[unDead][i].c-flowNet[unDead][i].f) ) ?
(flowNet[unDead][i].c-flowNet[unDead][i].f):pre[unDead].minF;
if(numV-1==i)
{
return true;
}
}
}
}
return false;
}
//Ford-Fulkerson
int Ford_Fulkerson()
{
pre[0].v=-1;
pre[0].minF=MAX;
memset(visited,0,sizeof(visited));
while(BFS()==true)
{
int nowV=numV-1;
int preV=pre[nowV].v;
int minF=pre[nowV].minF;
while(preV!=-1)
{
flowNet[preV][nowV].f+=minF;
flowNet[nowV][preV].f-=minF;
nowV=preV;
preV=pre[nowV].v;
}
memset(visited,0,sizeof(visited));
}
int totalFlow=0;
for(int i=1;i<numV;++i)
{
totalFlow+=flowNet[0][i].f>0? flowNet[0][i].f:0;
}
return totalFlow;
}
int main()
{
for(int i=0;i<numV;++i)
{
for(int j=0;j<numV;++j)
{
cin>>flowNet[i][j].c; //有边为实际容量,无边为0,flowNet(u,u)=0
flowNet[i][j].f=0;
}
}
cout<<Ford_Fulkerson()<<endl;
return 0;
}
/*
示意图:
(s)0 1 2 3 4 (t)5
(s)0 0 16 13 0 0 0
1 0 0 10 12 0 0
2 0 4 0 0 14 0
3 0 0 9 0 0 20
4 0 0 0 7 0 4
(t)5 0 0 0 0 0 0
复制粘贴的数据:
0 16 13 0 0 0
0 0 10 12 0 0
0 4 0 0 14 0
0 0 9 0 0 20
0 0 0 7 0 4
0 0 0 0 0 0
*/