您的位置:首页 > 其它

树的最小支配集poj3659、最小点覆盖、最大独立集

2017-10-09 19:56 483 查看
推荐讲解 点击打开链接

对于树图,贪心法求最小支配集、最小点覆盖、最大独立集。

最小支配集:选取尽量少的点组成一个集合,对图中任意一点u,在集合中一定存在于u相邻的点。



最小点覆盖:选取尽量少的点组成一个集合,对图中任意条边<u,v>,u,v至少有一点在集合中。



最大独立集:选取尽量多的点组成一个集合,集合中任意两点没有边。



三种题目的求法:

int pos[10101];//深搜顺序

int fa[10101];//父节点

int select[10101];//标记点是否选中支配集

都需要dfs预处理pos[]和fa[]数组(链式前向星)

void dfs(int s,int &k)
{
pos[k++]=s;
vis[s]=1;
for(int i=head[s];~i;i=e[i].next)
{
int t=e[i].t;
if(!vis[t])
{
fa[t]=s;
dfs(t,k);
}
}
}【最小支配集】:
int greedy(int root)
{
memset(vis,0,sizeof (vis));
int k=0;
fa[root]=root;//根节点的祖先视为自己!
dfs(root,k);//预处理
//if(k<n)return -1; //原图没有构成树
memset(vis,0,sizeof (vis));
memset(select,0,sizeof (select));
int ans=0;
for(int i=k-1;i>=0;i--)
{
int t=pos[i];
if(!vis[t])
{
if(!select[fa[t]])
{
select[fa[t]]=1;
ans++;
}
vis[t]=vis[fa[t]]=vis[fa[fa[t]]]=1;
}
}
return ans;
}
【最小点覆盖】:
int greedy(int root)
{
memset(vis,0,sizeof (vis));
int k=0;
fa[root]=root;//根节点的祖先视为自己!
dfs(root,k);//预处理
//if(k<n)return -1; //原图没有构成树
memset(vis,0,sizeof (vis));
memset(select,0,sizeof (select));
int ans=0;
for(int i=k-1;i>=0;i--)
{
int t=pos[i];
if(!vis[t]&&!vis[fa[t]])
{
select[fa[t]]=1;
ans++;
vis[t]=vis[fa[t]]=1;
}
}
return ans;
}
【最大独立集】:
int greedy(int root)
{
memset(vis,0,sizeof (vis));
int k=0;
fa[root]=root;//根节点的祖先视为自己!
dfs(root,k);//预处理
//if(k<n)return -1; //原图没有构成树
memset(vis,0,sizeof (vis));
memset(select,0,sizeof (select));
int ans=0;
for(int i=k-1;i>=0;i--)
{
int t=pos[i];
if(!vis[t])
{
select[t]=1;
ans++;
vis[t]=vis[fa[t]]=1;
}
}
return ans;
}


例题:

【poj3659 最小支配集】:

分析:john要在n个点中选一些点建信号塔,已知每个点可以收到自己点和相邻点的信号塔信号。

问最少要建几个塔。

【代码】:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
using namespace std;
struct node{
int s,t,next;
}e[20101];
int head[10101],cnt;
void add(int u,int v)
{
e[cnt]=node{u,v,head[u]};
head[u]=cnt++;
}
int pos[10101];//深搜顺序
int fa[10101];//父节点
bool vis[10101];
int select[10101];//标记点是否选中支配集
void dfs(int s,int &k)//预处理pos[]和fa[]
{
pos[k++]=s;
vis[s]=1;
for(int i=head[s];~i;i=e[i].next)
{
int t=e[i].t;
if(!vis[t])
{
fa[t]=s;
dfs(t,k);
}
}
}
int greedy(int root) { memset(vis,0,sizeof (vis)); int k=0; fa[root]=root;//根节点的祖先视为自己! dfs(root,k);//预处理 //if(k<n)return -1; //原图没有构成树 memset(vis,0,sizeof (vis)); memset(select,0,sizeof (select)); int ans=0; for(int i=k-1;i>=0;i--) { int t=pos[i]; if(!vis[t]) { if(!select[fa[t]]) { select[fa[t]]=1; ans++; } vis[t]=vis[fa[t]]=vis[fa[fa[t]]]=1; } } return ans; }
int main()
{
int n,u,v;
cin>>n;
memset(head,-1,sizeof(head));
cnt=0;
for(int i=1;i<n;i++)
{
cin>>u>>v;
add(u,v);
add(v,u);
}
printf("%d\n",greedy(1));
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: