hdu 4917Permutation(狀態壓縮DP)

來源:互聯網
上載者:User

標籤:dp

hdu 4917Permutation(狀態壓縮DP)

題意:將1~n的n個數排列成序列(n<=40),但有m(m<=20)個限制條件,其中第i個限制條件的表示為ai,bi。表示該序列的第ai的數要小於第bi的。問有多少中排列?保證有解

解法:我們首先可以明確一點,這m個限制條件,所表示的關係會構成若干個DAG(有向非循環圖,我將其稱之為拓撲圖)。我們只要將這n個數,填入到拓撲圖上,使其滿足拓撲關係,那麼這樣的序列就是可以的。而這若干個拓撲圖之間,是不會相互影響的,因而我們可以單獨考慮每一個拓撲圖。對於單獨的一個拓撲圖,假設有k個節點(即要放入k個數),隨便放入k個數,都可以構成解,而且無論放什麼,對於這個拓撲圖,能滿足條件的放法都是一樣多的,因此每一個拓撲圖要乘上一個組合數(選k個有多少種選法)。然後我們來考慮某個拓撲圖的內部放法。因為m<=20,那麼每個拓撲圖內最多有21個點。我們用狀態壓縮dp來解決這個問題。前面我們得知,無論選的k個數是什麼,在本拓撲圖內合法的排放序列都是一樣多的,我們不妨假設這k個位置為0~K-1,我們將k個數字按從大到小往圖上放,記dp[m]為,放好了二進位狀態為m(二進位1表示相應位表示的節點已填入了數字,0表示未放),dp從小到大遞推即可得解。而dp狀態轉移的條件是,我要填入某一位時,該位的前驅都已選入在m這個狀態中了,因此可以先處理拓撲圖,得到每一位的前驅。

代碼:

#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>#include<queue>#define ll __int64using namespace std ;vector<int> vec[44] ;const int mod = 1000000007 ;int dp[1<<21] ;int fa[44] , sz[44] , vis[44] ;int to[44] , id[44] , du[44] ;int c[44][44] ;void init () {    c[0][0] = 1 ;    for ( int i = 1 ; i < 44 ; i ++ ) {        c[i][0] = 1 ;        for ( int j = 1 ; j <= i ; j ++ )            c[i][j] = ( c[i-1][j] + c[i-1][j-1] ) % mod ;    }}int find ( int a ) {    return fa[a] == a ? a : fa[a] = find ( fa[a] ) ;}struct Point {    int id , st ;    Point () {}    Point (int a , int b):id(a),st(b) {}} ;int gao ( int s , int n , int& re) {    int tot = 0 ;    queue<Point> Q ;    for ( int i = 1 ; i <= n ; i ++ ) {        if ( find (i) == s && du[i] == 0 ) {            to[tot++] = 0 ;            Q.push ( Point(i,1<<tot-1) ) ;        }    }    while ( !Q.empty () ) {        Point u = Q.front () ;        int st = u.st ;        int f = u.id ;        Q.pop () ;        for ( int i = 0 ; i < vec[f].size () ; i ++ ) {            int v = vec[f][i] ;            du[v] -- ;            id[v] ¦= st ;            if ( du[v] == 0 ) {                to[tot++] = id[v] ;                Q.push ( Point(v,id[v]¦(1<<(tot-1))) ) ;            }        }    }    ll ret = c[re][tot] ; //   printf ( "ret = %I64d\n" , ret ) ;    re -= tot ;    dp[0] = 1 ;    for ( int i = 1 ; i < 1<<tot ; i ++ ) {        dp[i] = 0 ;        for ( int j = 0 ; j < tot ; j ++ ) {            if ( ((i&(1<<j))) ) {                int st = i ^ (1<<j) ;                if ( (~st)&to[j] ) continue ;                dp[i] += dp[i^(1<<j)] ;                dp[i] %= mod ;   //             printf ( "i = %d , to[%d] = %d\n" , i , j , to[j] ) ;   //             printf ( "dp[%d] = %d\n" , i , dp[i] ) ;            }        }    }//    printf ( "dp[%d] = %d\n" , (1<<tot)-1 , dp[(1<<tot)-1] ) ;    ret *= dp[(1<<tot)-1] ;    ret %= mod ;    return ret ;}int main () {    init () ;    int n , m ;    while ( scanf ( "%d%d" , &n , &m ) != EOF ) {        int re = n ;        memset ( vis , 0 , sizeof ( vis ) ) ;        for ( int i = 1 ; i <= n ; i ++ ) {            vec[i].clear () ;            fa[i] = i ;            du[i] = 0 ;            id[i] = 0 ;        }        for ( int i = 1 ; i <= m ; i ++ ) {            int a , b ;            scanf ( "%d%d" , &a , &b ) ;            vec[a].push_back ( b ) ;            du[b] ++ ;            int x = find ( a ) , y = find ( b ) ;            if ( x != y ) fa[x] = y ;        }        ll ans = 1 ;        for ( int i = 1 ; i <= n ; i ++ ) {            if ( !vis[find(i)] ) {                ans *= gao (find(i),n,re) ;                ans %= mod ;                vis[find(i)] = 1 ;            }        }        printf ( "%I64d\n" , ans ) ;    }    return 0 ;}/*3 21 21 34 31 21 31 44 41 21 32 43 46 61 21 33 42 44 54 68 92 13 15 14 26 37 58 48 68 75 43 13 24 35 3*/


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.