状压dp找寻环的个数 Codeforces Beta Round #11 D
Posted 不知姓名的黑猫君
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了状压dp找寻环的个数 Codeforces Beta Round #11 D相关的知识,希望对你有一定的参考价值。
http://codeforces.com/problemset/problem/11/D
题目大意:给你n个点,m条边,找该图中有几个换
思路:定义dp[i][j]表示i是圈的集合,j表示该集合的终点,定义起点为这些走过的点里面最小的
//看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #include <bits/stdc++.h> using namespace std; #define LL long long #define ALL(a) a.begin(), a.end() #define pb push_back #define mk make_pair #define fi first #define se second #define haha printf("haha\\n") const int maxn = 19; LL dp[1 << maxn][maxn + 5]; int a[maxn + 5][maxn + 5]; int n, m; void get_min(int val, int &cnt, int &st){ int pos = 0; while (val){ if (val & 1) st = min(st, pos), cnt++; val >>= 1; pos++; } } ///定义dp[i][j]表示i是圈的集合,j表示该集合的终点,定义起点为这些走过的点里面最小的 int main(){ cin >> n >> m; for (int i = 1; i <= m; i++){ int u, v; scanf("%d%d", &u, &v); u--, v--; a[u][v] = a[v][u] = 1; } LL ans = 0; for (int i = 0; i < n; i++) dp[1 << i][i] = 1;///初始化 for (int i = 1; i < (1 << n); i++){ int cnt = 0, st = n; get_min(i, cnt, st); for (int j = 0; j < n; j++){ if (dp[i][j]){///目前集合为i,终点为j。而且根据放入集合的顺序,j必然是在i集合里面的 if (a[st][j] && cnt >= 3){///放入集合的最终的终点一定得是在st的旁边。否则会将形不成环的放入ans中 ans += dp[i][j]; } for (int k = st + 1; k < n; k++){///放入终点大于st的。根据定义st必然为最小的起点。 ///然后k<st的已经在更小的状态中全部都计算过了 if (a[j][k] && !(i & (1 << k))){ dp[i | (1 << k)][k] += dp[i][j]; } } } } } /*haha; for(int i = 0; i < n; i++){ for (int j = 0; j < (1 << n); j++){ printf("%lld ", dp[j][i]); } cout << endl; }*/ cout << ans / 2 << endl; return 0; }
以上是关于状压dp找寻环的个数 Codeforces Beta Round #11 D的主要内容,如果未能解决你的问题,请参考以下文章
codeforces 1215 E Marbles-----状压DP
Codeforces Round #302 (Div. 1) C - Remembering Strings 状压dp
Codeforces1598 F. RBS(状压dp,预处理)
Codeforces 580D-Kefa and Dishes(状压DP)