BZOJ-1191: [HNOI2006]超级英雄Hero(网络流)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1191

明显是匹配,可以用网络流来写,对于每一个问题,连边,然后BFS找增广路,如果找不到就直接退出即可。

代码:

dbb44aed2e738bd40a77d148a38b87d6277ff971.jpg.png
#include 
#include 
#include 
#include 
 
using namespace std ;
 
#define MAXN 2010
 
struct edge {
    edge *next , *pair ;
    int t , f ;
} *head[ MAXN ] ;
 
void Add( int s , int t , int f ) {
    edge *p = new( edge ) ; 
    p -> t = t , p -> f = f , p -> next = head[ s ] ;
    head[ s ] = p ;
}
 
void AddEdge( int s , int t , int f ) {
    Add( s , t , f ) , Add( t , s , 0 ) ;
    head[ s ] -> pair = head[ t ] , head[ t ] -> pair = head[ s ] ;
}
 
int S , T , pre[ MAXN ] , n , m ;
bool f[ MAXN ] ;
edge *aug[ MAXN ] ;
queue < int > Q ;
 
bool bfs(  ) {
    memset( f , true , sizeof( f ) ) ; f[ S ] = false ;
    while ( ! Q.empty(  ) ) Q.pop(  ) ;
    Q.push( S ) ; pre[ S ] = 0 ;
    bool flag = false ;
    while ( ! Q.empty(  ) ) {
        int v = Q.front(  ) ; Q.pop(  ) ; 
        for ( edge *p = head[ v ] ; p ; p = p -> next ) if ( p -> f && f[ p -> t ] ) {
            f[ p -> t ] = false ; pre[ p -> t ] = v , aug[ p -> t ] = p ;
            Q.push( p -> t ) ;
            if ( p -> t == T ) {
                flag = true ; break ;
            }
        }
        if ( flag ) break ;
    }
    if ( f[ T ] ) return false ;
    for ( int i = T ; pre[ i ] ; i = pre[ i ] ) {
        aug[ i ] -> f -- , aug[ i ] -> pair -> f ++ ;
    }
    return true ;
}
 
int main(  ) {
    memset( head , 0 , sizeof( head ) ) ;
    scanf( "%d%d" , &n , &m ) ;
    T = n + m + 1 , S = n + m + 2 ;
    for ( int i = 0 ; i ++ < n ; ) AddEdge( i , T , 1 ) ;
    for ( int i = 0 ; i ++ < m ; ) {
        int x , y ; scanf( "%d%d" , &x ,&y ) ;
        AddEdge( S , n + i , 1 ) , AddEdge( n + i , x + 1 , 1 ) , AddEdge( n + i , y + 1 , 1 ) ;
        if ( ! bfs(  ) ) {
            printf( "%d\n" , i - 1 ) ;
            return 0 ;
        }
    }
    printf( "%d\n" , m ) ;
    return 0 ;
}

你可能感兴趣的:(BZOJ-1191: [HNOI2006]超级英雄Hero(网络流))