BZOJ 1797: [Ahoi2009]Mincut 最小割

本文介绍了一个利用残余网络进行流量分配的高效算法。通过BFS遍历网络,确定各节点与源节点S或目标节点T的连通性,并在此基础上计算最大流。算法最终输出满足特定条件的边,用于优化网络资源分配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个很好用的结论:

对残余网络的S与T分别作bfs,得出每个点是否和S/T在同一连通块中

一条x到y的单向边

满足1:当x,y不同时属于S/T连通块且该边满流

满足2:当x,y分别属于S与T连通块且该边满流

CODE:

#include<cstdio>

#include<iostream>

#include<cstring>

#include<algorithm>

#include<queue>

using namespace std;

#define maxn 4010

#define maxm 60100

struct edges{

int to,next,cap;

}edge[maxm*2];

int s,t,next[maxn],l,n,m;

void addedge(int x,int y,int z){

l++;

edge[l*2]=(edges){y,next[x],z};next[x]=l*2;

edge[l*2+1]=(edges){x,next[y],0};next[y]=l*2+1;

}

#define inf 0x7fffffff

int gap[maxn],h[maxn],p[maxn];

int sap(int u,int flow){

if (u==t) return flow;

int cnt=0;

for (int i=p[u];i;i=edge[i].next)

if (edge[i].cap&&h[edge[i].to]+1==h[u]) {

int cur=sap(edge[i].to,min(flow-cnt,edge[i].cap));

edge[i].cap-=cur;edge[i^1].cap+=cur;

p[u]=i;

if ((cnt+=cur)==flow) return flow;

}

if (!(--gap[h[u]])) h[s]=n;

gap[++h[u]]++;

p[u]=next[u];

return cnt;

}

int maxflow(){

memset(gap,0,sizeof(gap));

memset(h,0,sizeof(h));

for (int i=1;i<=n;i++) p[i]=next[i];

gap[0]=n;

int flow=0; 

while (h[s]<n) flow+=sap(s,inf);

return flow;

}

queue<int> q;

int ans[2][maxm];

bool b[maxm][2];

int bfs(int x,int y) {

q.push(x);

while (!q.empty()) {

int u=q.front();q.pop();

b[u][y]=1;

for (int i=next[u];i;i=edge[i].next)

if (edge[i^y].cap&&!b[edge[i].to][y]) q.push(edge[i].to);

}

return 0;

}

int main(){

scanf("%d%d%d%d",&n,&m,&s,&t);

for (int i=1;i<=m;i++) {

int x,y,z;

scanf("%d%d%d",&x,&y,&z);

addedge(x,y,z);

}

maxflow();

bfs(s,0);bfs(t,1);

for (int i=1;i<=l;i++) {

if (!edge[i*2].cap){

int u=edge[i*2].to,v=edge[i*2+1].to;

if ((b[u][0]&&b[v][1])||(b[u][1]&&b[v][0])) ans[1][i]=1;

if (!((b[u][0]&&b[v][0])||(b[u][1]&&b[v][1]))) ans[0][i]=1;

}

}

for (int i=1;i<=m;i++) printf("%d %d\n",ans[0][i],ans[1][i]);

return 0;

}


转载于:https://www.cnblogs.com/New-Godess/p/4348903.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值