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;
}

猜你喜欢

转载自www.cnblogs.com/chdy/p/12620394.html