题目链接:点我啊╭(╯^╰)╮
题目大意:
n n n 个点,求所有能组成的集的最大独立集的和
解题思路:
n
≤
26
n≤26
n≤26,所以可以 状压
d
p
dp
dp
a
x
a_x
ax 表示
x
x
x 这个点连的边的状态
l
b
x
lb_x
lbx 表示
x
x
x 二进制中最低位为
1
1
1 的位置
__
b
u
i
l
t
i
n
builtin
builtin_
c
t
z
(
x
)
ctz(x)
ctz(x) 表示
x
x
x 末尾有多少个
0
0
0
d
p
[
x
]
dp[x]
dp[x] 表示
x
x
x 这个集的最大独立集的
s
i
z
e
size
size
然后随便删去一个点,
x
x
x 的
d
p
dp
dp 值即为删去后的答案与未删的答案
+
1
+1
+1 取
m
a
x
max
max
d
p
[
x
]
=
m
a
x
(
d
p
[
x
⨁
l
b
]
,
c
h
a
r
(
d
p
[
x
dp[x] = max(dp[x \bigoplus lb], char(dp[x
dp[x]=max(dp[x⨁lb],char(dp[x &
(
a
[
_
_
b
u
i
l
t
i
n
_
c
t
z
(
x
)
]
)
]
+
1
)
)
(~a[\_\_builtin \_ctz(x)])] + 1))
( a[__builtin_ctz(x)])]+1))
P
S
:
PS:
PS:题目卡内存。。用
4
4
4 字节的
i
n
t
int
int 会爆
需要用
1
1
1 字节的
c
h
a
r
char
char ,最多只能存
255
>
n
255 > n
255>n
核心:位元状压dp与独立集的应用
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
using pii = pair <ll,int>;
int n, m, a[26];
ll ans;
char dp[(1<<26) + 5];
int lowbit(int x){
return x & (-x);
}
int main() {
scanf("%d%d", &n, &m);
while(m--){
int u, v;
scanf("%d%d", &u, &v);
a[u] |= (1<<v);
a[v] |= (1<<u);
}
for(int i=0; i<n; i++) a[i] |= (1<<i);
for(int s=1; s<(1<<n); s++){
int lb = lowbit(s);
dp[s] = max(dp[s^lb], char(dp[s&(~a[__builtin_ctz(s)])] + 1));
ans += int(dp[s]);
}
printf("%lld\n", ans);
}