zoukankan      html  css  js  c++  java
  • CodeForces11D 状压dp

    http://codeforces.com/problemset/problem/11/D

    题意 给定一个简单图,输出其中的简单环的数目。简单环的含义是,不包含重复顶点、重复边的环。

    1 <= n <= 19

    这题看数据范围很显然用状压dp来做,但是和寻常的状压dp由很大的差别,一开始想用记忆化搜索的方法,dp[i]表示这个状态下的最大简单环数量,但是在状态转移的过程中发现并不容易去转移。

    事实上可以换一个思路,用dp来记录图中一个起点到一个重点的简单路径的数量,当终点返回到起点的时候, ans += dp

    但是三维的dp空间复杂度不允许,我们可以降低起点的维度,将起点变为状态中最小的点即可。

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Scl(x) scanf("%lld",&x);  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x);  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    typedef vector<int> VI;
    const double eps = 1e-9;
    const int maxn = 20;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    int N,M,tmp,K;
    LL dp[1 << 19][maxn]; 
    bool vis[1 << 19];
    struct Edge{
        int v,next;
    }edge[maxn * maxn];
    int head[maxn],tot;
    bool MAP[maxn][maxn];
    void add(int u,int v){
        MAP[u][v] = 1;
        edge[++tot].v = v;
        edge[tot].next = head[u];
        head[u] = tot;
    }
    int findfirst(int x){
        int cnt = 0;
        while(x){
            if(x & 1) break;
            cnt++;
            x >>= 1;
        }
        return cnt;
    }
    int main()
    {
        scanf("%d%d",&N,&M);
        For(i,1,M){
            int u,v; Sca2(u,v);u--,v--;
            add(u,v); add(v,u);
        }
        For(i,0,N - 1){
            dp[1 << i][i] = 1;
        }
        LL ans = 0;
        for(int t = 1; t < (1 << N) ; t ++){
            int st = findfirst(t);
            for(int x = 0;x < N ; x ++){
                if(t & (1 << x) && dp[t][x]){
                    for(int i = st; i < N ; i ++){
                        if(MAP[x][i]){
                            if(t & (1 << i)){
                                if(t == ((1 << i) | (1 << x))) continue;
                                if(i == st) ans += dp[t][x];
                            }else dp[t | (1 << i)][i] += dp[t][x];
                        }
                    }
                }
            }
        }
        Prl(ans / 2);
        #ifdef VSCode
        system("pause");
        #endif
        return 0;
    }
  • 相关阅读:
    XMPP serverejabberd-14.12本地搭建
    uva 699 The Falling Leaves(建二叉树同一时候求和)
    ORA-22828 输入样式或替换參数超过了32k限制大小
    Timus 1149. Sinus Dances 打印复杂公式
    POJ2226
    3149 爱改名的小融 2
    1169 传纸条 2008年NOIP全国联赛提高组 个人博客:attack.cf
    1019 集合论与图论
    1215 迷宫
    1020 孪生蜘蛛
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/9607841.html
Copyright © 2011-2022 走看看