codeforces 11D(状压dp)

传送门:https://codeforces.com/problemset/problem/11/D

题意:

求n个点m条边的图里面环的个数

题解:

点的范围只有19,很容易想到是状压。

dp[sta][a]表示状态为sta,终点为n时环的个数

转移:

dp[sta | (1 << i)][i] += dp[sta][e];

由于是无向边,所以答案会重复计算一遍,最后要记得除2

代码:

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef long long ll;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"

const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 3e2 + 5;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
int mp[20][20];
LL dp[1 << 20][20];
int main() {
#ifndef ONLINE_JUDGE
    FIN
#endif
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        u--;
        v--;
        mp[u][v] = mp[v][u] = 1;
    }
    memset(dp, 0, sizeof(dp));
    for(int i = 0; i < n; i++) {
        dp[1 << i][i] = 1;
    }
    LL ans = 0;
    for(int s = 1; s < (1 << n); s++) {//枚举状态
        int st = 0;
        for(int i = 0; i < n; i++) {//枚举起点
            if(s & (1 << i)) {
                st = i;
                break;
            }
        }
        for(int e = st; e < n; e++) {//枚举终点
            if(s & (1 << e)) {
                for(int i = st; i < n; i++) {//从起点到终点
                    if(!(s & (1 << i)) && mp[e][i]) {
                        dp[s | (1 << i)][i] += dp[s][e];
                        if (mp[i][st] && __builtin_popcount(s | (1 << i)) >= 3)//环中点的个数
                            ans += dp[s][e];
                    }
                }
            }
        }
    }
    printf("%lld\n", ans / 2);
    return 0;
}#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef long long ll;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"

const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 3e2 + 5;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
int mp[20][20];
LL dp[1 << 20][20];
int main() {
#ifndef ONLINE_JUDGE
    FIN
#endif
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        u--;
        v--;
        mp[u][v] = mp[v][u] = 1;
    }
    memset(dp, 0, sizeof(dp));
    for(int i = 0; i < n; i++) {
        dp[1 << i][i] = 1;
    }
    LL ans = 0;
    for(int s = 1; s < (1 << n); s++) {//枚举状态
        int st = 0;
        for(int i = 0; i < n; i++) {//枚举起点
            if(s & (1 << i)) {
                st = i;
                break;
            }
        }
        for(int e = st; e < n; e++) {//枚举终点
            if(s & (1 << e)) {
                for(int i = st; i < n; i++) {//从起点到终点
                    if(!(s & (1 << i)) && mp[e][i]) {
                        dp[s | (1 << i)][i] += dp[s][e];
                        if (mp[i][st] && __builtin_popcount(s | (1 << i)) >= 3)//环中点的个数
                            ans += dp[s][e];
                    }
                }
            }
        }
    }
    printf("%lld\n", ans / 2);
    return 0;
}
posted @ 2019-06-18 09:30  buerdepepeqi  阅读(395)  评论(0编辑  收藏  举报