定义
大概就是:连通图,每条边最多只属于一个环
用处
解别人出的毒瘤题
出毒瘤题
反正要学。。。
习题
仙人掌的最大独立集
###做法
没有环就是树 D P DP DP
碰到环就做一遍环上的 D P DP DP就好了,枚举一下一个点是否选即可
# include <bits/stdc++.h>
# define IL inline
# define RG register
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
const int maxn(2e5 + 5);
int n, m, dfn[maxn], low[maxn], idx, fa[maxn], f[2][maxn], ans;
struct Edge{
int first[maxn], cnt, nxt[maxn], to[maxn];
IL void Init(){
cnt = 0, Fill(first, -1);
}
IL void Add(RG int u, RG int v){
nxt[cnt] = first[u], to[cnt] = v, first[u] = cnt++;
}
} e1;
IL void Solve(RG int x, RG int u){
RG int f0 = f[0][x], f1 = max(f[1][x], f[0][x]);
for(RG int i = fa[x]; i != u; i = fa[i]){
RG int tmp = f0;
f0 = f1 + f[0][i], f1 = max(f0, tmp + max(f[0][i], f[1][i]));
}
f[0][u] += max(f1, f0), f0 = f1 = f[0][x];
for(RG int i = fa[x]; i != u; i = fa[i]){
RG int tmp = f0;
f0 = f1 + f[0][i], f1 = max(f0, tmp + max(f[0][i], f[1][i]));
}
f[1][u] += f0;
}
IL void Tarjan(RG int u, RG int fe){
dfn[u] = low[u] = ++idx, f[1][u] =1, f[0][u] = 0;
for(RG int e = e1.first[u]; e != -1; e = e1.nxt[e]){
RG int v = e1.to[e];
if(e == fe) continue;
if(!dfn[v]) fa[v] = u, Tarjan(v, e ^ 1), low[u] = min(low[u], low[v]);
else low[u] = min(low[u], dfn[v]);
if(low