判断边是否在某个最小割集中 以及 判断边是否为最小割的必需边。
在残余网络中求出强连通分量,对于不在同一强连通分量且满流的边,必然在某一最小割中。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define min(a,b) ( (a)< (b)? (a): (b) )
int const N= 4010, M= 60010;
struct Edge{
int adj, flow, idx;
Edge* next;
}tb[M<<1];
int n, m, S, T, cnt;
Edge* mat[N];
inline void add( int u, int v, int idx, int f ){
++cnt;
tb[cnt].adj= v; tb[cnt].flow= f; tb[cnt].idx= idx;
tb[cnt].next= mat[u]; mat[u]= tb+ cnt;
++cnt;
tb[cnt].adj= u; tb[cnt].flow= 0; tb[cnt].idx= 0;
tb[cnt].next= mat[v]; mat[v]= tb+ cnt;
}
inline Edge* reserve( Edge* p ){
return tb+ ( (p- tb)^ 1 ); }
int que[N], head, tail, ht[N];
int bfs(){
for( int i= 0; i<= n; ++i ) ht[i]= -1;
que[0]= S; head= tail= 0; ht[S]= 0;
while( head<= tail ){
int u= que[head++];
for( Edge* p= mat[u]; p; p= p->next )
if( ht[p->adj]== -1 && p->flow ){
ht[p->adj]= ht[u]+ 1;
que[++tail]= p->adj;
}
}
return ht[T]!= -1;
}
int dfs( int u, int flow ){
if( u== T ) return flow;
int tf= 0, f;
for( Edge* p= mat[u]; p; p= p->next )
if( ht[p->adj]== ht[u]+ 1 && p->flow && flow> tf &&
( f= dfs( p->adj, min( p->flow, flow- tf ) ) ) ){
reserve( p )->flow+= f;
p->flow-= f;
tf+= f;
}
if( tf== 0 ) ht[u]= -1;
return tf;
}
int dep[M], low[M], ind[N], stack[N], top, num, id;
void SCC( int u ){
dep[u]= low[u]= ++num; stack[++top]= u;
for( Edge* p= mat[u]; p; p= p->next )
if( p->flow ){
int v= p->adj;
if( dep[v]== 0 ){
SCC( v );
if( low[v]< low[u] ) low[u]= low[v];
}
else if( low[v]!= n && dep[v]< low[u] )
low[u]= low[v];
}
if( dep[u]== low[u] ){
id++;
do{
ind[ stack[top] ]= id;
low[ stack[top] ]= n;
}while( stack[top--]!= u );
}
}
void solve(){
for( int i= 0; i<= n; ++i ){
dep[i]= 0; low[i]= 0; ind[i]= 0; }
num= 0; id= 0; top= -1;
for( int i= 1; i<= n; ++i )
if( dep[i]== 0 ) SCC( i );
for( int i= 0; i<= m; ++i ){
dep[i]= 0; low[i]= 0; }
for( int u= 1; u<= n; ++u )
for( Edge* p= mat[u]; p; p= p->next ){
int v= p->adj;
if( ind[u]!= ind[v] && p->flow== 0 ) dep[p->idx]= 1;
if( ind[u]!= ind[v] && p->flow== 0 &&
ind[u]== ind[S] && ind[v]== ind[T] ) low[p->idx]= 1;
}
for( int i= 1; i<= m; ++i )
printf("%d %d\n", dep[i], low[i] );
}
int main(){
while( scanf("%d%d%d%d", &n, &m, &S, &T )!= EOF ){
cnt= -1;
for( int i= 0; i<= n; ++i ) mat[i]= 0;
int u, v, d;
for( int i= 1; i<= m; ++i ){
scanf("%d%d%d", &u, &v, &d );
add( u, v, i, d );
}
int ans= 0;
while( bfs() ) ans+= dfs( S, 0x7fffffff );
solve();
}
return 0;
}