【BZOJ4316】小C的獨立集(動態規劃)

#【BZOJ4316】小C的獨立集(動態規劃) ##題面 BZOJ ##題解 考慮樹的獨立集求法 設$f[i][0/1]$表示$i$這個點必定不選,以及$i$這個點無所謂的最大值 轉移$f[u][0]=\sum f[v][1]$,$f[u][1]=\sum f[v][0]$,$f[u][1]=max(f[u][1],f[u][0])$ 如今放在了仙人掌上, 咱們能夠看作一棵樹加上了若干不相交的返祖邊 因而再加上一維$f[u][0/1][0/1]$ 其中最後一維表示這條邊所在的環的最底端的那個點必定不選,或者無所謂 賦初值:$f[u][1][1]=1$,若是這個點不是所在環的最底端,$f[u][1][0]=1$ 此時的轉移: 1.兩個點的底端點相同 這個時候咱們先只考慮強制不選底端的轉移 那麼,$f[u][1][0]+=f[v][1][1],f[u][1][1]+=f[v][1][0]$ 也就是上面裸的在樹上的轉移php

2.兩個點的底端點不一樣 既然跨越了環,意味着$u$就是這個環的底端點,$v$是它所在環的頂端點 那麼,能夠$u$選$v$不選,由於跨越了環,因此對於$v$的底端點選擇與否咱們是不關心的 而第二維的$1$表示的$u$無所謂,後面的$0$則是強制不選擇$u$ 所以$f[u][0][0]+=f[v][1][1]$,$f[u][1][0]+=f[v][0][0]$ios

3.$v$的頂端點不是$u$ 意味着不用擔憂底端點產生的影響 因此$f[u][0][1]+=f[v][1][1]$,$f[u][1][1]+=f[v][0][1]$spa

4.$v$的頂端點是$u$ 此時要考慮底端點的貢獻了 此時當前$u$不選,那就沒有什麼問題$f[u][0][1]+=f[v][1][1]$ 當前$u$選擇,強制不能選擇底端點$f[u][1][1]+=f[v][0][0]$code

好了,這樣就討論完了四種轉移,而後就能夠啦get

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 55555
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
struct Line{int v,next;}e[MAX*3];
int h[MAX],cnt=1,n,m;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
int dep[MAX],fa[MAX];
int tp[MAX],un[MAX];
void dfs(int u,int ff)
{
	fa[u]=ff;dep[u]=dep[ff]+1;
	for(int i=h[u];i;i=e[i].next)
		if(!dep[e[i].v])dfs(e[i].v,u);
}
void jump(int u,int v){int x=v;while(x!=u)tp[x]=u,un[x]=v,x=fa[x];}
int f0[MAX],f1[MAX],g0[MAX],g1[MAX];
void dp(int u)
{
	f1[u]=1;
	if(u!=un[u])g1[u]=1;
	for(int i=h[u];i;i=e[i].next)
	{
		int v=e[i].v;if(dep[u]+1!=dep[v])continue;
		dp(v);
		if(un[u]!=un[v])g0[u]+=f1[v],g1[u]+=g0[v];
		else g0[u]+=g1[v],g1[u]+=g0[v];
		if(tp[v]!=u)f0[u]+=f1[v],f1[u]+=f0[v];
		else f0[u]+=f1[v],f1[u]+=g0[v];
	}
	f1[u]=max(f1[u],f0[u]);
	g1[u]=max(g1[u],g0[u]);
}
int main()
{
	n=read();m=read();
	for(int i=1;i<=m;++i)
	{
		int u=read(),v=read();
		Add(u,v);Add(v,u);
	}
	dfs(1,0);
	for(int u=1;u<=n;++u)
		for(int i=h[u];i;i=e[i].next)
			if(dep[u]<dep[e[i].v]&&fa[e[i].v]!=u)
				jump(u,e[i].v);
	dp(1);
	printf("%d\n",f1[1]);
	return 0;
}
相關文章
相關標籤/搜索