LOJ6009「网络流 24 题 - 10」软件补丁 最小代价转移 SPFA状态压缩

大家都很强, 可与之共勉 。

题意:
  不好概括啊
  

题解:
  发现 n 很小,于是状态压缩。看是否能够到0这个状态,跑最短路就可以了。

  LOJ越来越慢了

# include <bits/stdc++.h>

template < class T >  inline bool chkmin ( T& d, const T& x )  {  return d > x ? ( d = x ), 1 : 0 ;  }

# define N 210
# define oo 0x3f3f3f3f

int w [N] ;
int dis [1 << 20 | 1] ;
int f1 [N], f2 [N], b1 [N], b2 [N] ;

inline int Spfa ( int S, int T, int m )  {
    static std :: bitset < 1 << 20 | 1 > inq ;
    static std :: deque < int > Q ;
    inq.reset ( ) ; Q.clear ( ) ;
    memset ( dis, 0x3f, sizeof dis ) ;
    Q.push_front ( S ) ;
    inq [S] = 1 ;
    dis [S] = 0 ;
    while ( ! Q.empty ( ) )  {
        int u = Q.front ( ) ; Q.pop_front ( ) ;
        inq [u] = 0 ;
        for ( int i = 0 ; i < m ; ++ i )
            if ( ( u & b1 [i] ) == b1 [i] && ( u & b2 [i] ) == 0 )  {
                int v = ( ( u ^ ( u & f1 [i] ) ) | f2 [i] ) ;
            //  int v = ( ( u & ( ~f1 [i] ) ) ) | f2 [i] ;
                if ( chkmin ( dis [v], dis [u] + w [i] ) )  {
                    if ( ! inq [v] )  {
                        ( Q.empty ( ) || dis [v] < dis [Q.front ( )] ) ? Q.push_front ( v ) : Q.push_back ( v ) ;
                        inq [v] = 1 ;
                    }
                }
        }
    }
    return dis [T] == oo ? 0 : dis [T] ;
}

# undef N

int main ( )  {
    int n, m ;
    scanf ( "%d%d", & n, & m ) ;
    for ( int i = 0 ; i < m ; ++ i )  {
        scanf ( "%d", w + i ) ;
        static char buf [50] ;
        scanf ( "%s", buf ) ;
        for ( int k = 0 ; k < n ; ++ k )
            if ( buf [k] == '+' )  {
                b1 [i] |= 1 << k ;
            }  else if ( buf [k] == '-' )  {
                b2 [i] |= 1 << k ;
            }
        scanf ( "%s", buf ) ;
        for ( int k = 0 ; k < n ; ++ k )
            if ( buf [k] == '-' )  {
                f1 [i] |= 1 << k ;
            }  else if ( buf [k] == '+' )  {
                f2 [i] |= 1 << k ;
            }
    }
    printf ( "%d\n", Spfa ( ( 1 << n ) - 1, 0, m ) ) ;
    return 0 ;
}       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值