• poj 3592 Instantaneous Transference(强连通分支 +spfa)


    题意:给出一个N*M的矩形,每个小矩形里有的有一定数量的矿物,有的有传输的功能,有的不能通过,每个小矩形里的矿物只能采集一次,问你最多能过采集多少的矿物。

    思路:强连通分支+spfa,先求出强连通分支,在强连通分支中,所以点都是可达的,然后进行缩点,将每一个连通分支看做一个点,而这个点的矿物容量就是这个强连通分支中所有点的和,然后在用一下spfa求最大的矿物量。

    PS:因为没注意一个循环的长度,导致我查了一个下午加一个晚上,泪~~,细心!细心啊!

    代码:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <math.h>
    #define N 2004
    #define M 50
    #define T 200020
    using namespace std ;
    
    struct node
    {
        int u ;
        int v ;
        int val ;
        int next ;
    }p[T] , d[T] ;
    
    int head1[N] , head2[N] ;
    int dfn[N] , low[N] ;
    int dis[N] , vist[N] ;
    int belong[N] , sum[N] , valx[N] ;
    int st[N] , q[N] , f[N] ;
    int n , m , cnt , num1 , num2 , res , index , all ;
    int top ;
    
    void add( int x , int y )
    {
        p[num1].u = x ;
        p[num1].v = y ;
        p[num1].next = head1[x] ;
        head1[x] = num1++ ;
    }
    
    void add2( int  x , int y , int c )
    {
        d[num2].u = x ;
        d[num2].v = y ;
        d[num2].val = c ;
        d[num2].next = head2[x] ;
        head2[x] = num2++ ;
    }
    
    int min( int x , int y )
    {
        return x < y ? x : y ;
    }
    
    void dfs( int x )
    {
        int y , u ;
    
        dfn[x] = low[x] = index++ ;
        st[top++] = x ;
        f[x] = 1;
        for ( y = head1[x] ; y != -1 ; y = p[y].next )
        {
            u = p[y].v ;
            if ( !dfn[u] )
            {
                dfs( u ) ;
                low[x] = min( low[x] , low[u] );
            }
            else if ( f[u] )
            low[x] = min( low[x] , dfn[u] ) ;
        }
        if ( dfn[x] == low[x] )
        {
            res++ ;
            do
            {
                y = st[--top] ;
                f[y] = 0 ;
                belong[y] = res ;
            }while( y != x ) ;
        }
    }
    
    void Tarjan()
    {
        int i ;
        memset( dfn , 0 , sizeof( dfn ));
        memset( low , 0 , sizeof( low ));
        memset( st , 0 , sizeof ( st ));
        memset( f , 0 , sizeof ( f )) ;
        top = 0 ;index = 1 ;res = 0 ;
        for ( i = 0 ; i < all ; i++ )
        if ( !dfn[i] )
        dfs( i );
    
        memset( sum , 0 , sizeof ( sum )) ;
        for ( i = 0 ; i < all ; i++ )
        sum[belong[i]] += valx[i] ;
    }
    
    void slove( int s )
    {
        int x , y ;
        int len = res + 1 ;
        memset( q , 0 , sizeof( q ));
        for( x = 0 ; x < len ; x++ )
        {
            dis[x] = -1 ;
            vist[x] = 0 ;
        }
        dis[s] = 0 ;
        //vist[s] = 1 ;
        int head = 0 ;
        int tail = 0 ;
        q[head++] = s ;
    
        while( head != tail )
        {
            x = q[tail++] ;
            vist[x] = 0 ;
            if ( tail == N ) tail = 0 ;
            for ( y = head2[x] ; y != -1 ;  y = d[y].next )
            {
                int v = d[y].v ;
                if ( dis[v] < dis[x] + d[y].val )
                {
                    dis[v] = dis[x] + d[y].val ;
                    if( !vist[v] )
                    {
                        vist[v] = 1 ;
                        q[head++] = v ;
                        if ( head == N ) head = 0 ;
                    }
                }
            }
        }
    }
    
    int spfa()
    {
        int i , j ;
        num2 = 2 ;
        memset( head2 , -1 , sizeof( head2 )) ;
        add2( 0 , belong[0] , sum[belong[0]] ) ;
        for ( i = 0 ; i < all ; i++ )
        {
            for ( j = head1[i] ; j != -1 ; j = p[j].next )
            {
                int v = p[j].v ;
                if ( belong[i] != belong[v] )
                add2( belong[i] , belong[v] , sum[belong[v]] );
            }
        }
        slove( 0 );
    
        int maxx = 0 ;
        for ( i = 1 ; i <= res ; i++ )
        if ( dis[i] > maxx )
        maxx = dis[i] ;
        return maxx ;
    }
    
    void work()
    {
        int i , j , r , c , k ;
        char str[M][M] ;
        int data[M][M] , pos[N] ;
        int dir[2][2] = {{-1, 0} , {0 ,-1}} ;
    
        all = 0 ; num1 = 2 ;k = 0 ;
        memset( head1 , -1 , sizeof ( head1 ));
        scanf( "%d%d" , &n , &m ) ;
        for ( i = 0 ; i < n ; i++ )
        {
            scanf ( "%s" , str[i] );
            for ( j = 0 ; j < m ; j++ )
            {
                if ( str[i][j] == '#' )
                continue ;
                data[i][j] = all++ ;
                if ( str[i][j] >= '0' && str[i][j] <= '9')
                {
                    valx[data[i][j]] = str[i][j] - '0' ;
                }
                else
                {
                    valx[data[i][j]] = 0 ;
                }
    
                if ( str[i][j] == '*' )
                {
                    pos[k++] = data[i][j] ;
                }
                for ( int xx = 0 ; xx < 2 ; xx++ )
                {
                    r = i + dir[xx][0] ;
                    c = j + dir[xx][1] ;
                    if( r >= 0 && c >= 0 )
                    {
                        if ( str[r][c] == '#' )
                        continue ;
                        add( data[r][c] , data[i][j] );
                    }
                }
            }
        }
        for ( i = 0 ; i < k ; i++ )
        {
            scanf ( "%d%d" , &r , &c ) ;
            if ( str[r][c] == '#' )
            continue ;
            add( pos[i] , data[r][c] );
        }
        Tarjan();
    
        int ans = spfa( );
        printf ( "%d\n" , ans );
    }
    
    int main()
    {
        int cas ;
    
        scanf( "%d" , &cas );
        while ( cas-- )
        {
            work();
        }
        return 0 ;
    }
  • 相关阅读:
    保障系统的稳定性
    Ubuntu 16.04开启SSH服务
    Linux中tty是什么(tty1~7)
    Linux显示使用命令who(转)
    Linux去重命令uniq(转)
    Linux文字分段裁剪命令cut(转)
    Linux排序命令sort(转)
    Linux查找字符串命令grep(转)
    Linux文件查找命令find(转)
    Ubuntu查看和写入系统日志
  • 原文地址:https://www.cnblogs.com/misty1/p/2615581.html
Copyright © 2020-2023  润新知