以后会逐渐完善,现在会先存放一些代码
广义圆方树对于每个仙人掌的环新建一个方点,原仙人掌上的点为圆点,向这个环上的所有圆点连边,使得所有的边连接的都是 $ 1 $ 个圆点和 $ 1 $ 个方点
广义圆方树长这个样子
然后就可以用树形 dp 的方法来解决很多仙人掌上的问题啦
bzoj 4316(求仙人掌最大独立集
建出圆方树,进行树形 dp
对于圆点 $ i $,记 $ f_{i,0} $ 表示不选取 i,i 子树的最大独立集,$ f_{i,1} $ 表示 $ i $ 子树的最大独立集
然后要注意一下在原仙人掌上有连边的两个点不能同时选
如一个方点的父亲不能和它在原图里连的两个圆点同时选
感觉这个 dp 也不是很烦
扫描二维码关注公众号,回复:
4847356 查看本文章
#include <bits/stdc++.h>
#define CIOS ios::sync_with_stdio(false);
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
#define DEBUG(x) cerr << "DEBUG" << x << " >>> ";
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
template <typename T>
inline void read(T &f) {
f = 0; T fu = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') fu = -1; c = getchar(); }
while (c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = getchar(); }
f *= fu;
}
template <typename T>
void print(T x) {
if (x < 0) putchar('-'), x = -x;
if (x < 10) putchar(x + 48);
else print(x / 10), putchar(x % 10 + 48);
}
template <typename T>
void print(T x, char t) {
print(x); putchar(t);
}
const int N = 1e5 + 5;
vector <int> a[N], b[N];
int low[N], dfn[N], f[N][2], tmp[N][2], st[N], top;
int n, m, oldn, _time;
void tarjan(int u) {
st[++top] = u; low[u] = dfn[u] = ++_time;
for(register int i = 0; i < a[u].size(); i++) {
int v = a[u][i];
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u]) {
int tmp = 0; ++n;
while(tmp != v) {
tmp = st[top--];
b[n].push_back(tmp);
b[tmp].push_back(n);
}
b[u].push_back(n);
}
} else low[u] = min(low[u], dfn[v]);
}
}
void dfs(int u, int fa) {
if(u <= oldn) {
f[u][0] = 0; f[u][1] = 1;
for(register int i = 0; i < b[u].size(); i++) {
int v = b[u][i]; if(v == fa) continue; dfs(v, u);
f[u][0] += f[v][1]; f[u][1] += f[v][0];
}
f[u][1] = max(f[u][1], f[u][0]);
} else {
for(register int i = 0; i < b[u].size(); i++) dfs(b[u][i], u);
tmp[0][0] = tmp[0][1] = f[b[u][0]][0];
for(register int i = 1; i < b[u].size(); i++) {
int v = b[u][i];
tmp[i][0] = tmp[i - 1][1] + f[v][0];
tmp[i][1] = tmp[i - 1][0] + f[v][1];
tmp[i][1] = max(tmp[i][1], tmp[i][0]);
}
f[u][0] = tmp[b[u].size() - 1][0];
tmp[0][0] = f[b[u][0]][0]; tmp[0][1] = f[b[u][0]][1];
for(register int i = 1; i < b[u].size(); i++) {
int v = b[u][i];
tmp[i][0] = tmp[i - 1][1] + f[v][0];
tmp[i][1] = tmp[i - 1][0] + f[v][1];
tmp[i][1] = max(tmp[i][1], tmp[i][0]);
}
f[u][1] = tmp[b[u].size() - 1][1];
}
}
int main() {
read(n); read(m); oldn = n;
for(register int i = 1; i <= m; i++) {
int u, v; read(u); read(v);
a[u].push_back(v);
a[v].push_back(u);
}
tarjan(1); dfs(1, 0);
print(f[1][1], '\n');
return 0;
}
// Rotate Flower Round.