bzoj 4316 小C的独立集
LINK:小C的独立集
无向图的最大独立集问题是NPC的.
而树的独立集是固定的 二分图的最大独立集是网络流的(总点数-最大匹配数。
这道题是求出一张仙人掌图的最大独立集。
跟树差不多 我们考虑环 和非环的问题。
环上点比较特殊除了自己的儿子对自己有限制 还有环上两点对其的限制。
非环 直接树形dp解决即可。
所以分为两步 树形dp+环上dp解决 求环还是点双连通分量来求。
我这里换上dp的做法:拆换成链这里好像做不了,以前环的做法我也忘了。
考虑暴力枚举x的状态 发现只有2个 对于选 我们暴力钦定第2个点不选 最后一个点不选 这样就行了。
如果不选 那么第二个点和最后一个点无所谓。可以证明这样做是正确的。(便利了所有最优的状态空间。
inline void solve(int x)
{
g[2][0]=g[2][1]=f[a[2]][0];
rep(3,sum,i)
{
g[i][0]=max(g[i-1][1],g[i-1][0])+f[a[i]][0];
g[i][1]=g[i-1][0]+f[a[i]][1];
}
f[x][1]+=g[sum][0];//开头为0结尾也为0.
g[2][1]=f[a[2]][1];g[2][0]=f[a[2]][0];
rep(3,sum,i)
{
g[i][0]=max(g[i-1][1],g[i-1][0])+f[a[i]][0];
g[i][1]=g[i-1][0]+f[a[i]][1];
}
f[x][0]+=max(g[sum][0],g[sum][1]);
}
inline void dfs(int x)
{
dfn[x]=low[x]=++cnt;
s[++top]=x;f[x][1]=1;
go(x)
{
if(!dfn[tn])
{
dfs(tn);
low[x]=min(low[x],low[tn]);
if(low[tn]>=dfn[x])
{
int y=0;sum=0;
a[++sum]=x;
while(y!=tn)
{
y=s[top--];
a[++sum]=y;
}
solve(x);
}
}
else low[x]=min(low[x],dfn[tn]);
}
}
int main()
{
freopen("1.in","r",stdin);
get(n);get(m);
rep(1,m,i)
{
int x,y;
get(x);get(y);
add(x,y);add(y,x);
}
dfs(1);put(max(f[1][0],f[1][1]));
return 0;
}