最小割的可行边和必须边
可行边\((u,v)\)需要满足以下两个条件
-
满流
-
残量网络中不存在\(u\)到\(v\)的路径
这个挺好理解的呀,如果存在还存在路径的话那么这条边就不会是瓶颈了
必须边\((u,v)\)需要满足的条件
-
满流
-
残量网络中\(S\)能到达\(u\),\(v\)能到达\(T\)
这样的话\((u,v)\)就成为了唯一的瓶颈了
我们可以直接在残量网络上跑\(tarjan\),只跑没满流的边
如果发现\(u\)和\(v\)不在同一强联通分量里,就说明这是一条可行边
因为\((u,v)\)满流,\((v,u)\)必然存在,在同一连通分量里就说明可以从\(u\)走到\(v\)形成一个环,也就存在\(u\)到\(v\)的路径
如果\(u\)和\(S\)在同一个强联通分量里,\(v\)和\(T\)在同一个强连通分量里,那么说明这是一条必须边,和上面类似
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
const int maxn=4e3+5;
const int inf=1e9;
inline int read() {
char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
std::queue<int> q;
struct E{int v,nxt,f;}e[150000];
int n,m,S,T,cnt,top,p,mid,num=1;
int dfn[maxn],low[maxn],st[maxn],f[maxn];
int head[maxn],d[maxn],cur[maxn],col[maxn];
inline void C(int x,int y,int f) {
e[++num].v=y;e[num].nxt=head[x];
head[x]=num;e[num].f=f;
}
int X[60005],Y[60005],id[60005];
inline void add(int x,int y,int f) {C(x,y,f),C(y,x,0);}
inline int BFS() {
for(re int i=1;i<=n;i++) d[i]=0,cur[i]=head[i];
d[S]=1,q.push(S);
while(!q.empty()) {
int k=q.front();q.pop();
for(re int i=head[k];i;i=e[i].nxt)
if(!d[e[i].v]&&e[i].f) d[e[i].v]=d[k]+1,q.push(e[i].v);
}
return d[T];
}
int dfs(int x,int now) {
if(x==T||!now) return now;
int flow=0,ff;
for(re int& i=cur[x];i;i=e[i].nxt)
if(d[e[i].v]==d[x]+1) {
ff=dfs(e[i].v,min(e[i].f,now));
if(now<=0) continue;
now-=ff,flow+=ff,e[i].f-=ff,e[i^1].f+=ff;
if(!now) break;
}
return flow;
}
void tarjan(int x) {
dfn[x]=low[x]=++cnt;
st[++top]=x;f[x]=1;
for(re int i=head[x];i;i=e[i].nxt) {
if(!e[i].f) continue;
if(!dfn[e[i].v]) tarjan(e[i].v),low[x]=min(low[x],low[e[i].v]);
else if(f[e[i].v]) low[x]=min(low[x],dfn[e[i].v]);
}
if(dfn[x]==low[x]) {
++p;
do {
mid=st[top--];
f[mid]=0;
col[mid]=p;
}while(x!=mid);
}
}
int main() {
n=read(),m=read();S=read(),T=read();
for(re int z,i=1;i<=m;i++) {
X[i]=read(),Y[i]=read();
z=read();id[i]=num+1;add(X[i],Y[i],z);
}
while(BFS()) dfs(S,inf);
for(re int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
for(re int i=1;i<=m;i++) {
if(col[X[i]]!=col[Y[i]]&&!e[id[i]].f) putchar('1');
else putchar('0');
putchar(' ');
if(!e[id[i]].f&&col[X[i]]==col[S]&&col[Y[i]]==col[T]) putchar('1');
else putchar('0');
putchar(10);
}
return 0;
}