https://ac.nowcoder.com/acm/problem/15748
最大独立子集:选出尽量多的点,使得任何两个节点均不相邻,输出一个最大独立集。
最大独立子集
f[i][0/1]表示以i为根时最大独立点的数量,f[][0]--不住 f[][1]--住
则初始值为1,
v是u的儿子节点
//AC @author:AROY
#include<bits/stdc++.h>
using namespace std;
#define N 100005
ll n, k[N];
ll ans, f[N][2];//f[][0]--不住 f[][1]--住
ll tot,rt,dis[N],p[N],h[N],ne[N<<1],u[N<<1],wi[N<<1];
void add(int u,int v){p[++tot]=v;ne[tot]=h[u];h[u]=tot;}
void dfs(int u,int fa){
f[u][0]=0;f[u][1]=1;
for(int i=h[u];i;i=ne[i])if(p[i]!=fa)
{
int v=p[i];
dfs(p[i],u);
f[u][1]+=f[v][0];
f[u][0]+=max(f[v][0],f[v][1]);
}
}
int main()
{
int s;
cin>>n>>s;
for(int i=0;i<n;++i){
int u,v;cin>>u>>v;
add(u,v);add(v,u);
}
dfs(s,0);
cout<<f[s][1];
} 最小点覆盖
对于图G=(V,E)来说,最小点覆盖指的是从V中取尽量少的点组成一个集合,使得E中所有的边都与取出来的点相连
TODO
最小支配集
指的是从V中取尽量少的点组成一个集合,使得对于V中剩余的点都与取出来的点有边相连。
dp[i][0]:表示点i属于支配集,并且以点i为根的子树都被覆盖了的情况下支配集中所包含的的最少点的个数。
dp[i][1]:i不属于支配集,且以i为根的子树都被覆盖,且i被其中不少于1个子节点覆盖的情况下支配集中所包含最少点的个数。
dp[i][2]:i不属于支配集,且以i为根的子树都被覆盖,且i没被子节点覆盖的情况下支配集中所包含最少点的个数。
对于第一种状态,dp[i][0]等于每个儿子节点的3种状态(其儿子是否被覆盖没有关系)的最小值之和加1,即只要每个以i的儿子为根的子树都被覆盖,再加上当前点i,所需要的最少点的个数,方程如下:
void DP(int u,int p)
{
dp[u][2]=0;
dp[u][0]=1;
bool s=false;
int sum=0,inc=INF;
int k;
for(k=head[u];k!=-1;k=edge[k].next)
{
int to=edge[k].to;
if(to==p)continue;
DP(to,u);
dp[u][0]+=min(dp[to][0],min(dp[u][1],dp[u][2]));
if(dp[to][0]<=dp[to][1])
{
sum+=dp[to][0];
s=true;
}
else
{
sum+=dp[to][1];
inc=min(inc,dp[to][0]-dp[to][1]);
}
if(dp[to][1]!=INF&&dp[u][2]!=INF)dp[u][2]+=dp[to][1];
else dp[u][2]=INF;
}
if(inc==INF&&!s)dp[u][1]=INF;
else
{
dp[u][1]=sum;
if(!s)dp[u][1]+=inc;
}
} 
京公网安备 11010502036488号