题目链接 : 洛谷1345
题目大意
给出一个
N
个点
分析
1. 对于这种分离
S,T
的题,考虑最大流–最小割的方法。
2. 然而题目要求割点,而不是割边,怎么办?这就是一种经典的拆点题。
3. 把每个点
i
拆成两个点
4. 为什么要这样连边?这样可以保证最小割只割点,不割边。而且只能
i+n,j
连不能
j,i+n
连,后者会增大最大流。
5. 接下来就可以直接跑最大流–最小割了。
上代码
// 主要思路已在分析中给出,代码中不作多余阐述
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std ;
const int N = 300 + 5 ;
const int M = 3e3 + 5 ;
const int INF = 0x3f3f3f3f ;
int n, m, S, T ;
int len, head[ N ] ;
struct node_lib {
int to, val, next ;
inline void add( int a , int b , int c ) {
to = b, val = c, next = head[ a ] ;
head[ a ] = len ++ ;
}
} lib[ M << 1 ] ;
// 建图
inline void init() {
memset( head , 0xff , sizeof( head ) ) ;
scanf( "%d %d %d %d", &n ,&m, &S, &T ) ;
for ( int i = 1 ; i <= n ; i ++ )
if ( i == S || i == T ) {
lib[ len ].add( i , i + n , INF ) ;
lib[ len ].add( i + n , i , 0 ) ;
} else {
lib[ len ].add( i , i + n , 1 ) ;
lib[ len ].add( i + n , i , 0 ) ;
}
for ( int i = 1 ; i <= m ; i ++ ) {
int a, b ; scanf( "%d %d", &a, &b ) ;
lib[ len ].add( a + n , b , INF ) ;
lib[ len ].add( b , a + n , 0 ) ;
lib[ len ].add( b + n , a , INF ) ;
lib[ len ].add( a , b + n , 0 ) ;
}
}
queue < int > Q ;
int curn[ N ], step[ N ] ;
inline bool bfs() {
memset( step , 0 , sizeof( step ) ) ;
step[ S ] = 1 ; Q.push( S ) ;
while ( !Q.empty() ) {
int temp = Q.front() ; Q.pop() ;
for ( int p = head[ temp ] ; p != -1 ; p = lib[ p ].next ) {
int nown = lib[ p ].to ;
if ( !step[ nown ] && lib[ p ].val ) {
step[ nown ] = step[ temp ] + 1 ; Q.push( nown ) ;
}
}
}
if ( step[ T ] ) return true ;
else return false ;
}
int dinic( int a , int b ) {
if ( a == T ) return b ;
for ( int p = curn[ a ] ; p != -1 ; p = lib[ p ].next ) {
curn[ a ] = p ;
int nown = lib[ p ].to ;
if ( step[ nown ] == step[ a ] + 1 && lib[ p ].val ) {
int temp = dinic( nown , min( b , lib[ p ].val ) ) ;
if ( temp ) {
lib[ p ].val -= temp ;
lib[ p ^ 1 ].val += temp ;
return temp ;
}
}
}
return 0 ;
}
inline int figure() {
int ans = 0 ;
while ( bfs() ) {
for ( int i = 1 ; i <= n * 2 ; i ++ )
curn[ i ] = head[ i ] ;
while ( int temp = dinic( S , INF ) )
ans += temp ;
}
return ans ;
}
int main() {
init() ;
printf( "%d\n", figure() ) ;
return 0 ;
}
以上