您的位置:首页 > 其它

树上最大独立集,最小支配集,最小覆盖子集(贪心做法)

2017-11-27 20:36 351 查看
含义: 最小支配集:对于图G=(V,E),从V中取尽量少的点,组成V’;对于原图中的任意顶点u,属于集合V‘或者与V‘中的点相连;

            最小覆盖点集:对于图G=(V,E),从V中取尽量少的点,组成V’;对于原图中的任意一条边(u,v),u属于V'或者v属于V';

            最大独立子集:对于图G=(V,E)来说,最大独立集指的是从V中取尽量多的点组成一个集合,使得这些点之间没有边相连。

首先邻接表存下边,先以任意一个点为根,进行深度遍历,记录每个节点的父节点并得到深度遍历序列;

#include <iostream>
#include <string.h>
using namespace std;
const int maxn=1e5+10;
struct point {
int next;
int to;
};
point pt[maxn*2];
int q,k;
int head[maxn*2],fa[maxn],sto[maxn];
bool dis[maxn],re[maxn],vis[maxn];
void add(int u,int v)
{
pt[q].next=head[u];
pt[q].to=v;
head[u]=q++;
}
void dfs(int st)
{
for (int i=head[st];i!=-1;i=pt[i].next)
{
int v=pt[i].to;
if (!vis[v])
{
vis[v]=true;
dfs(v);
fa[v]=st;
sto[k++]=v;
}
}
}
①最小支配集:按照深度优先进行反向检查,如果当前点不属于支配集也不与支配集中的点相连,如果他的父亲不属于支配集,将其父节点加入支配集,支配集中点的个数加一,标记当前节点,当前节点的父亲节点,当前节点的父亲节点的父亲节点,这些点或者属于支配集,或者与支配集中的点相连;

int min_zhi()
{
memset(re,false,sizeof(re));
memset(dis,false,sizeof(dis));
int ans=0;
for (int i=0;i<k;i++)
{
int va=sto[i];
if (!dis[va])
{
if (!re[fa[va]])
{
re[fa[va]]=true;
ans++;
}
dis[va]=dis[fa[va]]=dis[fa[fa[va]]]=true;
}
}
return ans;
}

②最小覆盖自子集:如果当前点和当前点的父亲节点都不属于顶点覆盖集合,将其父节点加入到顶点覆盖集合,并标记当前节点和当前节点的父节点;
int min_fu()
{
memset(re,false,sizeof(re));
memset(dis,false,sizeof(dis));
int ans=0;
for (int i=0;i<k;i++)
{
int va=sto[i];
if (!dis[va]&&!dis[fa[va]])
{
re[fa[va]]=true;
ans++;
dis[va]=dis[fa[va]]=true;
}
}
return ans;
}

③最大独立集:如果当前点没有被覆盖,则加入当前点到独立集中,并标记此节点和其父亲节点都被覆盖;
int max_du()
{
memset(re,false,sizeof(re));
memset(dis,false,sizeof(dis));
int ans=0;
for (int i=0;i<k;i++)
{
int va=sto[i];
if (!dis[va])
{
re[fa[va]]=true;
ans++;
dis[va]=dis[fa[va]]=true;
}
}
return ans;
}

主函数:
int main()
{
int n,m,u,v;
while (scanf("%d%d",&n,&m))
{
memset(head,-1,sizeof(head));
q=1,k=0;
for (int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
memset(vis,false,sizeof(vis));
vis[1]=true;
fa[1]=1; (设1为根节点)
dfs(1);
for (int i=0;i<k;i++)
cout<<sto[i]<<"***";
cout<<endl;
for (int i=1;i<=10;i++)
cout<<fa[i]<<" ";
cout<<endl;
printf("%d\n",min_zhi());
for (int i=1;i<=10;i++)
cout<<re[i]<<" ";
cout<<endl;
printf("%d\n",min_fu());
for (int i=1;i<=10;i++)
cout<<re[i]<<" ";
cout<<endl;
printf("%d\n",max_du());
for (int i=1;i<=10;i++)
cout<<re[i]<<" ";
cout<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  贪心