树上的最大独立集

过程详见入门经典第二版280页,粘代码跑QAQ

 1 #include "iostream"
 2 #include "cstdio"
 3 #include "cstring"
 4 #include "string"
 5 #include "vector"
 6 using namespace std;
 7 const int maxn=1000+10;
 8 int n;
 9 vector<int> g[maxn];
10 int son[maxn],gson[maxn];
11 int f[maxn],dp[maxn],wide[maxn];
12 int wide_max;
13 void init(){
14     scanf("%d",&n);
15     for(int i=1;i<n;i++){
16         int x,y;
17         scanf("%d%d",&x,&y);
18         g[x].push_back(y);
19         g[y].push_back(x);
20     }
21 }
22 void dfs(int v,int fa){
23     int d=g[v].size();
24     if(fa==-1)
25         wide[v]=0;
26     else
27         wide[v]=wide[fa]+1;
28     if(wide[v]>wide_max)
29         wide_max=wide[v];
30     for(int i=0;i<d;i++){
31         int k=g[v][i];
32         if(k!=fa)
33             dfs(k,f[k]=v);
34     }
35 }
36 int treedp(int root){
37     f[root]=-1;
38     wide_max=-1;
39     dfs(root,-1);
40     for(int i=wide_max;i>=0;i--){
41         for(int j=1;j<=n;j++){
42             if(wide[j]==i){
43                 dp[j]=max(son[j],gson[j]+1);
44                 if(i>=1)
45                     son[f[j]]+=dp[j];
46                 if(i>=2)
47                     gson[f[f[j]]]+=dp[j];
48             }
49         }
50     }
51     return dp[root];
52 }
53 int solve(){
54     int ans=0;
55     for(int i=1;i<=n;i++){
56         memset(son,0,sizeof(son));
57         memset(gson,0,sizeof(gson));
58         ans=max(ans,treedp(i));
59     }
60     return ans;
61 }
62 int main()
63 {
64     init();
65     int ans=solve();
66     printf("%d\n",ans);
67     return 0;
68 }

时间: 2024-10-05 23:36:22

树上的最大独立集的相关文章

hdu2412 Party at Hali-Bula

题目描述: n个人形成一个关系树,每个节点代表一个人,节点的根表示这个人的唯一的直接上司,只有根没有上司.要求选取一部分人出来,使得每2个人之间不能有直接的上下级的关系,求最多能选多少个人出来,并且求出获得最大人数的选人方案是否唯一. 解题思路: 模型:树上的最大独立集 方法:树形dp 分析: dp[u][0]和dup[u][0]表示以u为根的子树中,不选u点得到的最大人数以及方案唯一性(dup[u][0]=1表示唯一,0表示不唯一). dp[u][1]和dup[u][1]表示以u为根的子树中,

树的问题小结(最小生成树、次小生成树、最小树形图、LCA、最小支配集、最小点覆盖、最大独立集)

树的定义:连通无回路的无向图是一棵树. 有关树的问题: 1.最小生成树. 2.次小生成树. 3.有向图的最小树形图. 4.LCA(树上两点的最近公共祖先). 5.树的最小支配集.最小点覆盖.最大独立集. 一.最小生成树 解决的问题是:求无向图中边权值之和最小的生成树. 算法有Kruskal和Prim. Kruskal使用前向星和并查集实现,可以存储重边(平行边),时间复杂度是O(m log m  +  m),m是边的数量. Prim使用邻接矩阵建图,不可以存储重边(平行边),如果出现重边,存储的

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

定义: 最小支配集:对于图G = (V, E) 来说,最小支配集指的是从 V 中取尽量少的点组成一个集合, 使得 V 中剩余的点都与取出来的点有边相连.也就是说,设 V' 是图的一个支配集,则对于图中的任意一个顶点 u ,要么属于集合 V', 要么与 V' 中的顶点相邻. 在 V' 中除去任何元素后 V' 不再是支配集, 则支配集 V' 是极小支配集.称G 的所有支配集中顶点个数最少的支配集为最小支配集,最小支配集中的顶点个数称为支配数. 最小点覆盖:对于图G = (V, E) 来说,最小点覆盖

hdu1520 Anniversary party(最大独立集 树形dp)

题目链接:点击打开链接 题目描述:现有一棵树,树上每个结点都有一个权值,问从中选一些点,这些点两两之间不直接连接,问权值最大为多少? 解题思路:很裸的一道树上最大独立集问题 树形dp即可 dp[i][0]:不选i节点 dp[i][0]+=max(dp[t][0],dp[t][1]); dp[i][1]:选i节点     dp[i][1]+=dp[t][0]; 代码: #pragma comment(linker,"/STACK:1024000000,1024000000") #incl

树的最小支配集 最小点覆盖 与 最大独立集 (图论)

做 战略游戏 这道题的时候看到了这个东西,于是就来这里写了一下. 首先看一下三者的定义: 定义1 对于图G=(V,E)来说,最小支配集指的是从V中取尽量少的点组成一个集合,使得对于V中剩余的点都与取出来的点有边相连.也就是说,设V‘是图G的一个支配集,则对于图中的任意一个顶点u,要么属于集合V’,要么与V‘中的顶点相邻.在V’中出去任何元素后V‘不再是支配集,则支配集是极小支配集.称G的所有支配集中顶点个数最少的支配集为最小支配集,最小支配集中顶点的个数称为支配数. 定义2 对于图G=(V,E)

【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树

这题真刺激...... I.关于Kruskal重构树,我只能开门了,不过补充一下那玩意还是一棵满二叉树.(看一下内容之前请先进门坐一坐) II.原来只是用树上倍增求Lca,但其实树上倍增是一种方法,Lca只是他的一种应用,他可以搞各种树上问题,树上倍增一般都会用到f数组. |||.我们跑出来dfs序就能在他的上面进行主席树了. IV.别忘了离散. V.他可能不连通,我一开始想到了,但是我觉得出题人可能会是好(S)人(B),但是...... #include <cstdio> #include

【POJ3659】【USACO 2008 Jan Gold】 3.Cell Phone Network 树上最小支配集/贪心 两种做法

题意:求树上最小支配集 最小支配集:点集,即每个点可以"支配"到相邻点,求最少点数可以使所有点被支配. 图上的最小支配集是NP的,但是树上的可以DP做,是O(n)的. 暴力做就好了, f[i]表示此 点被选时的子树全支配的最小代价 g[i]表示其父亲节 点被选时的子树全支配的最小代价 h[i]表示其某子节 点被选时的子树全支配的最小代价 然后暴力转移. (v是子节点) f[x]=∑(min(f[v],min(g[v],h[v])))+1; g[x]=∑(min(f[v],h[v]));

HDU 1045 - Fire Net (最大独立集)

题意:给你一个正方形棋盘.每个棋子可以直线攻击,除非隔着石头.现在要求所有棋子都不互相攻击,问最多可以放多少个棋子. 这个题可以用搜索来做.每个棋子考虑放与不放两种情况,然后再判断是否能互相攻击来剪枝.最后取可以放置的最大值. 这里我转化成求最大独立集来做. 首先将每个空地编号,对于每个空地,与该位置可以攻击到的空地连边.找最多的空地使得不互相攻击,即求该图的最大独立集.与搜索做法基本一致,但是说法略有不同. 1 #include<iostream> 2 #include<cstring

【NOIP2015】运输计划(树上差分,二分答案)

题意:一棵有边权的树上有m条路径,要求选择一条边使其边权变为0,使得最大路径长度和最小 n,m<=300000 思路:直接求最优方案不可做,但检验对于某一个ans是否能有方案是可行的 取出所有总长度>ans的路径,求它们的交,取交集中长度最大的一条,设值为c[i],总长度最长的设为max 比较max-c[i]与ans的关系即可 路径求交因为是离线的,可以暴力树剖,也可以分类讨论维护路径交 但对于这个离线的问题,可以差分来做 对于路径(a[i],b[i]),设c[i]=lca 分为a[i]到lc