1.基本概念

对图G=<V,E>,

最小支配集:从V中取尽量少的点组成一个集合,使得V中剩余的点都与取出来的点有边相连

最小点覆盖:从V中取尽量少的点组成一个集合,使得E中所有边都与取出来的点相连

最大独立集:从V中取尽量多的点组成一个集合,使得这些点之间没有边相连

 

2.贪心法求树的最小支配集,最小点覆盖,最大独立集模板

基本算法:

以最小支配集为例,首先选择一点为根,按照深度优先遍历得到遍历序列,按照所得序列的反向序列的顺序进行贪心,对于一个既不属于支配集也不与支配集中的点相连的点来说,如果他的父节点不属于支配集,将其父节点加入支配集。

struct Edge
{
    int v,next;
}G[M];

int fa[N];
int vis[N];
int pos[N],head[N];
int now;
int n,m;

void DFS(int u)
{
    pos[now++] = u;
    for(int i=head[u];i!=-1;i=G[i].next)
    {
        int v = G[i].v;
        if(!vis[v])
        {
            vis[v] = 1;
            fa[v] = u;
            DFS(v);
        } 
    }
}
int MDS()
{
    int s[N] = {0};
    int set[N] = {0};
    int ans = 0;
    for(int i=now-1;i>=0;i--)
    {
        int t = pos[i];
        if(!s[t])
        {
            if(!set[fa[t]])
            {
                set[fa[t]] = 1;
                ans++;
            }
            s[t] = 1;
            s[fa[t]] = 1;
            s[fa[fa[t]]] = 1;
        }
    }
    return ans;
}
最小支配集MDS
int MPC()
{
    int s[N] = {0};
    int set[N] = {0};
    int ans = 0;
    for(int i=now-1;i>=0;i--)
    {
        int t = pos[i];
        if(!s[t] && !s[fa[t]])
        {
            set[fa[t]] = 1;
            ans++;
            s[t] = 1;
            s[fa[t]] = 1;
        }
    }
    return ans;
}
最小点覆盖MPC
int MIS()
{
    int s[N] = {0};
    int set[N] = {0};
    int ans = 0;
    for(int i=now-1;i>=0;i--)
    {
        int t = pos[i];
        if(!s[t])
        {
            set[t] = 1;
            ans++;
            s[t] = 1;
            s[fa[t]] = 1;
        }
    }
    return ans;
}
最大独立集MIS

相关文章: