[BZOJ1497]-tarjan (or extended row) + minimum cut

In the front

The data of this question If the data on luogu is the official data of that year, it's a bit too water
When me mistakenly called the dfs function in the fix ﹣ dfs function, I could get 80 points???
(this small error me is always invisible to the naked eye, and then a random set of data me is created Interesting)

subject

BZOJ1565 transfer gate
It's not very difficult, and it's not interesting to generalize
Poke gate







solution

Draw the dependency of the sample, and you will know the way to do this problem immediately

It can be found that this is a, to select the current lattice, you must first select the lattice pointing to it, turn the arrow back, this is a closed subgraph, and then the maximum weight closed subgraph. Of course, it's not over yet. If there is a ring in the picture, it means that zombies will die no matter which grid they are advanced in, then this ring can't be selected, and the grids pointed by this ring can't be selected. So you need to flag these unselected grids. You can do this with tarjan and topoport.
That's it

Here is the code with large constants

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

const int inf = 0x3f3f3f3f ;
bool flag[605] ;
int N , M , stp , shead[605] , score[605] , ind[605] ;
int tp = 1 , head[605] , maxn , S , T ;
struct Path{
    int pre , to , flow ;
}sp[360005] , p[360005] ;

int code( int i , int j ){ return i * M + j + 1 ; }
pair<int,int> decode( int x ){ return make_pair( ( x-1 )/M , ( x-1 )%M ) ;}

void sIn( int t1 , int t2 ){
    sp[++stp] = ( Path ){ shead[t1] , t2 , 0 } ;
    shead[t1] = stp ;
}
void In( int t1 , int t2 , int t3 ){
    p[++tp] = ( Path ){ head[t1] , t2 , t3 } ;
    head[t1] = tp ;
}

int sta[605] , topp ;
int dfn[605] , dfs_c , scc[605] , scc_cnt ;
int dfs( int u ){
    sta[++topp] = u ;
    int lowu = dfn[u] = ++dfs_c ;
    for( int i = shead[u] ; i ; i = sp[i].pre ){
        int v = sp[i].to ;
        if( !dfn[v] ) lowu = min( lowu , dfs( v ) ) ;
        else if( !scc[v] ) lowu = min( lowu , dfn[v] ) ;
    }
    if( lowu == dfn[u] ){
        scc_cnt ++ ;
        int tmp = topp ;
        while( 1 ){
            int x = sta[topp--] ;
            scc[x] = scc_cnt ;
            if( x == u ) break ;
        }
        if( tmp - topp > 1 )
        for( int i = topp + 1 ; i <= tmp ; i ++ )
            flag[ sta[i] ] = true ;
    } return lowu ;
}

void fix_dfs( int u ){
    flag[u] = true ;
    for( int i = shead[u] ; i ; i = sp[i].pre )
        if( !flag[ sp[i].to ] ) fix_dfs( sp[i].to ) ;
}

int dis[605] , que[605] , fr , ba ;
bool BFS(){
    memset( dis , -1 , sizeof( dis ) ) ;
    fr = 1 , ba = 0 ;
    dis[S] = 0 ; que[++ba] = S ;
    while( fr <= ba ){
        int u = que[fr++] ;
        for( int i = head[u] ; i ; i = p[i].pre ){
            int v = p[i].to ;
            if( dis[v] != -1 || !p[i].flow ) continue ;
            dis[v] = dis[u] + 1 ;
            que[++ba] = v ;
        }
    } return dis[T] != -1 ;
}

int dfs( int u , int flow ){
    if( u == T || !flow ) return flow ;
    int rt = 0 ;
    for( int i = head[u] ; i ; i = p[i].pre ){
        int v = p[i].to , nowf ;
        if( dis[v] != dis[u] + 1 || !p[i].flow ) continue ;
        nowf = dfs( v , min( flow , p[i].flow ) ) ;
        if( nowf ){
            rt += nowf ;
            flow -= nowf ;
            p[i].flow -= nowf ;
            p[i^1].flow += nowf ;
            if( !flow ) break ;
        }
    } if( !rt ) dis[u] = -1 ;
    return rt ;
}

void solve(){
    S = maxn + 1 , T = S + 1 ;
    for( int i = maxn ; i ; i -- )
        if( !dfn[i] ) dfs( i ) ;
    for( int i = maxn ; i ; i -- )
        if( flag[i] ) fix_dfs( i ) ;
    int ans = 0 ;
    for( int u = 1 ; u <= maxn ; u ++ ){
        if( flag[u] ) continue ;
        if( score[u] > 0 ){
            ans += score[u] ;
            In( S , u , score[u] ) ;
            In( u , S , 0 ) ;
        } else {
            In( u , T , -score[u] ) ;
            In( T , u , 0 ) ;
        } for( int i = shead[u] ; i ; i = sp[i].pre ){
            int v = sp[i].to ;
            if( !flag[v] ){
                In( v , u , inf ) ;
                In( u , v , 0 ) ;
            }
        }
    }
    while( BFS() )
        ans -= dfs( S , inf ) ;
    printf( "%d" , ans ) ;
}

int main(){
    scanf( "%d%d" , &N , &M ) ; maxn = N * M ;
    for( int i = 0 ; i < N ; i ++ ){
        for( int j = 0 , w ; j < M ; j ++ ){
            int now = code( i , j ) ;
            scanf( "%d%d" , &score[now] , &w ) ;
            for( int k = 1 , li , co ; k <= w ; k ++ ){
                scanf( "%d%d" , &li , &co ) ;
                sIn( now , code( li , co ) ) ;
            }
            if( j ) sIn( now , now - 1 ) ;
        }
    }
    solve() ;
}

Posted by ibbo on Mon, 04 May 2020 02:18:04 -0700