树dp:边覆盖,点覆盖
Posted a-blog-of-taojiayi-2003
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树dp:边覆盖,点覆盖相关的知识,希望对你有一定的参考价值。
#493. 求树的最小支配集
问题描述
对于一棵n个结点的无根树,求它的最小支配集。 最小支配集:指从所有顶点中取尽量少的点组成一个集合,使得剩下的所有点都与取出来的点有边相连。顶点个数最小的支配集被称为最小支配集。
输入格式
第一行一个整数n,表示结点数。接下来n-1行,每行两个整数a,b,表示结点a和b有边。
输出格式
一行,一个整数,表示最小支配集中元素的个数。
输入样例
9
2 5
2 7
2 8
9 2
3 2
3 1
3 6
4 3
输出样例
2
限制与预定
1 < n <=100000
时间限制:1s
空间限制:128mb
#include<cstdio> using namespace std; const int maxn=1e5+5; int n,f[maxn][3]; //0->儿子,1->父亲,2->自己 inline int min(int a,int b){ return(a<b?a:b); } inline void read(int &ans){ ans=0;int b=1; char x=getchar(); while(x<‘0‘ || ‘9‘<x){ if(x==‘-‘)b=-1; x=getchar(); } while(‘0‘<=x && x<=‘9‘){ ans=(ans<<3)+(ans<<1)+x-‘0‘; x=getchar(); } ans*=b; } int edge_count=0,to[maxn*2],next[maxn*2],first[maxn]; inline void add_edge(int x,int y){ edge_count++; to[edge_count]=y; next[edge_count]=first[x]; first[x]=edge_count; } void search(int root,int fa) { int pos=0; for(int i=first[root];i;i=next[i]){ if(to[i]==fa)continue; search(to[i],root); f[root][2]+=f[ to[i] ][1]; f[root][1]+=min(f[ to[i] ][2],f[ to[i] ][0]);//+最小值 if( f[ to[i] ][2]-f[ to[i] ][0] < f[pos][2]-f[pos][0] ) pos=to[i]; } f[root][2]++; if(f[root][1]>f[root][2])f[root][1]=f[root][2]; bool fd=1; for( int i=first[root];i;i=next[i] ){ if(to[i]==fa)continue; fd=0; if(to[i]==pos){ f[root][0]+=f[pos][2]; } else{ f[root][0]+=min(f[to[i]][0],f[to[i]][2]); } } f[root][0]+=fd; //if(root==9||root==8||root==7||root==5)printf("%d %d",root,f[root][0]); //if(f[root][0]||f[root][1]||f[root][2] )printf("%d",root); //if(root==1)printf("%d",f[1][0]); } int main() { //freopen("2.in","r",stdin); read(n); for( int i=1,a,b;i<n;i++){ read(a);read(b); add_edge(a,b); add_edge(b,a); } f[0][2]=0x7fffffff; search(1,0); printf("%d",min(f[1][0],min(f[1][1]+1,f[1][2]))); return 0; }
以上是关于树dp:边覆盖,点覆盖的主要内容,如果未能解决你的问题,请参考以下文章
树形dp——覆盖所有边的最少费用(Protecting Zonk)
uva12093Protecting Zonk (树形DP)
POJ 3659 Cell Phone Network (树dp)