一道树状dp,在处理子问题上的做法真的就是单纯的标准dfs树状dp。从叶子节点向上枚举可以得到每个节点的最大子树,但这题的问题在于,没有给出根节点,而且每个节点都可以作为根节点。
那么我们只需要枚举每个结点作为根节点时的情况。在每种情况中,遍历与根结点相连的结点,求出以该节点为根节点的最大子树。此时我们先选定的结点可能连着多个子树,但是我们只能选择一条链,所以选择最大的两个子树进行连接,剩下的子树都只能选择一条边。
#include<iostream> #include<cstdio> #include<cmath> using namespace std; int f[300005],head[300005],n,m,tot=0,ans=0,maxx,son[300005]; struct Edge { int to,nxt; }edge[900005]; void add(int u,int v) { edge[++tot].to=v; edge[tot].nxt=head[u]; head[u]=tot; } void dfs(int u,int fa) { int v,dade=0,xiaode=0; for(int i=head[u];i;i=edge[i].nxt) { v=edge[i].to; if(v!=fa) { dfs(v,u); if(f[v]>xiaode) { if(f[v]>dade) { xiaode=dade; dade=f[v]; } else xiaode=f[v]; } f[u]=max(f[u],f[v]+son[u]-1); } } ans=max(ans,xiaode+dade+son[u]-1); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int u,v; cin>>u>>v; add(u,v); add(v,u); son[u]++; son[v]++; } for(int i=1;i<=n;i++) f[i]=1; dfs(1,0); cout<<ans; return 0; }
原文地址:https://www.cnblogs.com/charlesss/p/10335938.html
时间: 2024-10-20 11:45:18