ZROI#1007

ZROI#1007

也是看起来非常不可做的一个题.

仔细思考,发现了一个很\(coool\)的事情:

他是不是让我求最小独立集覆盖...

一个独立集覆盖是指把图划分成若干个子集,每个子集里的点两两互不连通.

然后你\(2^n\)枚举子集,记录是不是一个独立集,然后在独立集上\(DP\).

你就令\(f_S\)表示点集为\(S\)时的最小独立集覆盖.

显然,每次可以从它一个是独立集的子集转移过来,取一个\(min\)就完了(最长路最短).

最后的答案是\(f_{U}-1\),其中\(U\)是全集.为什么减一啊?

因为最长路是边数啊...

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <cmath>
#include <ctime>
#include <map>
#include <set>
#define MEM(x,y) memset ( x , y , sizeof ( x ) )
#define rep(i,a,b) for (int i = (a) ; i <= (b) ; ++ i)
#define per(i,a,b) for (int i = (a) ; i >= (b) ; -- i)
#define pii pair < int , int >
#define one first
#define two second
#define rint read<int>
#define int long long
#define pb push_back

using std::queue ;
using std::set ;
using std::pair ;
using std::max ;
using std::min ;
using std::priority_queue ;
using std::vector ;
using std::swap ;
using std::sort ;
using std::unique ;
using std::greater ;

template < class T >
    inline T read () {
        T x = 0 , f = 1 ; char ch = getchar () ;
        while ( ch < '0' || ch > '9' ) {
            if ( ch == '-' ) f = - 1 ;
            ch = getchar () ;
        }
       while ( ch >= '0' && ch <= '9' ) {
            x = ( x << 3 ) + ( x << 1 ) + ( ch - 48 ) ;
            ch = getchar () ;
       }
   return f * x ;
}

const int N = 20 ;
const int MAXS = 1 << 20 ;
int n , m , ans , s[N] ;
int g[MAXS] , f[MAXS] , cnt ;
bool e[N][N] ;

inline bool judge () {
    rep ( i , 1 , cnt ) rep ( j , 1 , cnt )
        if ( e[s[i]][s[j]] || e[s[j]][s[i]] ) return false ;
    return true ;
}

signed main (int argc , char * argv[]) {
    n = rint () ; m = rint () ;
    rep ( i , 1 , m ) {
        int u = rint () , v = rint () ;
        e[u][v] = e[v][u] = true ;
    }
    int maxsize = 1 << n ;
    for (int i = 0 ; i < maxsize ; ++ i) {
        cnt = 0 ;
        for (int j = 0 ; j < n ; ++ j)
            if ( i & ( 1 << j ) )
                s[++cnt] = j + 1 ;
        g[i] = judge () ;
    }
    MEM ( f , 0x7f ) ; f[0] = 0 ;
    for (int i = 0 ; i < maxsize ; ++ i) {
        for (int j = i ; j ; j = ( j - 1 ) & i )
            if ( ! g[j] ) continue ;
            else f[i] = min ( f[i] , f[i^j] + 1 ) ;
    }
    printf ("%lld\n" , f[maxsize-1] - 1 ) ;
    return 0 ;
}
上一篇:ZROI十一集训Day2


下一篇:ZROI#1000