题目

最小割的可行边和必须边

可行边\((u,v)\)需要满足以下两个条件

  1. 满流

  2. 残量网络中不存在\(u\)\(v\)的路径

这个挺好理解的呀,如果存在还存在路径的话那么这条边就不会是瓶颈了

必须边\((u,v)\)需要满足的条件

  1. 满流

  2. 残量网络中\(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;
}