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;
}
每一个不曾刷题的日子
都是对生命的辜负
从弱小到强大,需要一段时间的沉淀,就是现在了
~buerdepepeqi