最大流最小割经典例题_C/C++知识点之最大流最小割C++实现

本文详细介绍了如何使用C++实现最大流最小割算法。通过具体代码展示了一个完整的求解最大流的实例,包括算法核心部分的逻辑解释,并在最后提供了完整的主函数示例,帮助理解算法的运用。
摘要由CSDN通过智能技术生成

using namespace std;

const int MAX=100;

const int inf=1<<30;

queueQ;

int ShortestAugmentingPath(int n,int source,int sink,int map[][MAX],int flow[][MAX],int pre_t[])

{

/*  n为顶点数 ,source为源点,sink为汇点,map[][]记录对应边的最大容量,flow[][]记录对应边具有的正流量;

最后一次迭代的pre_t[]记录了最小割,pre_t[i] !=0 表示属于源点集合  */

if(source==sink)  //特殊情况处理

return inf;

int i,x;

int visited[MAX];    //visited[i]=1表示顶点i被标记

int rest[MAX][MAX];  //rest[i][j]表示顶点i到j的未使用流量

int L[MAX];   //L[i]记录一次迭代过程中节点i的最大增量

int pre[MAX]; //pre[i]=0表示顶点i未标记,pre[i] >0 表示前向边,pre[i] 

//数组初始化

memset(rest,0,sizeof(rest));

memset(visited,0,sizeof(visited));

memset(flow,0,(n+1)*sizeof(flow[0]));

memset(L,0x7f,n*sizeof(L[0]));

memset(pre,0,sizeof(pre));

pre[source]=source+1;  //任意赋值为一个整数

while(!Q.empty())

Q.pop();

Q.push(source);  //最初,源点入队

while(!Q.empty())

{

visited[source]=1;  //源点被标记

i=Q.front();

Q.pop();

for(x=1;x<=n;x++) //前向边

{

if(i!=x&&!visited[x]&&map[i][x]!=inf)

{

rest[i][x]=map[i][x]-flow[i][x];

if( rest[i][x] > 0 )

{

L[x]=L[i] 

Q.push(x);

visited[x]=1;

pre[x]=i;

}

}

}

for(x=1;x<=n;x++)  //后向边

{

if(i!=x&&!visited[x]&&map[x][i]!=inf)

{

if(flow[x][i] > 0)

{

L[x]=L[i] 

Q.push(x);

visited[x]=1;

pre[x]=-i;

}

}

}

for(int y=1;y<=n;y++)  //记录最后一次迭代结果的标记,即为最小割

pre_t[y]=pre[y];

if(visited[sink]==1) //汇点被标记了

{

x=sink;

while(x!=source) //从汇点开始用第二个标记反向移动

{

if(pre[x]>0)

flow[i][x] += L[sink];

else

flow[i][x] -= L[sink];

x=i;

if(pre[i]>0 )

i=pre[i];

else

i=-pre[i];

}

memset(visited,0,sizeof(visited)); //擦除标记

memset(L,0x7f,n*sizeof(L[0]));

while(!Q.empty())

Q.pop();

Q.push(source); //用源点对q重新初始化

memset(pre,0,sizeof(pre));

pre[source]=1;

}

}

int maxflow=0;

for(i=1; i <= n;i++)

maxflow+=flow[i][sink];

return maxflow;

}

int main()

{

int map[MAX][MAX],flow[MAX][MAX],pre[MAX];

int n,i,x,w;

cout<

while(cin>>n && n)

{

for(i=1;i<=n;i++)

{

for(x=1;x<=n;x++)

map[i][x]=inf;

}

int m; //输入边数

cout<

cin>>m;

cout<

while(m--)

{

cin>>i>>x>>w;

map[i][x]=w;

}

cout<

cout<

for(i=1;i<=n;i++)

{

if(pre[i]!=0 )

cout<

}

cout<

for(i=1;i<=n;i++)

{

if(pre[i]==0)

cout<

}

cout<

}

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值