Luo Gu P2607 solution to a problem

Want in-depth study tree DP, please click on my blog .


DP model this problem with the P1352 no party boss . Difficulty of the problem is how to ring the tree into common tree DP DP.

Consider broken edge change and root. Wherein the first to find a ring, taken at random in the above two points, two points of disconnection side, so that it becomes a normal tree. To do that which is the root of a tree DP, and then to do it again another point as the root tree DP, because the adjacent two points can not be selected at the same time, the final statistics about \ (f (i) (0 ) \ ) and \ (g (j) (0 ) \) maximum can.

Definition of \ (f (i) (0/1 ) \) is the first tree DP \ (I \) optimum point, \ (G (I) (0/1) \) for the second the tree DP \ (I \) optimum point. $ \ text {Ans} $ is a tree ring DP answer. \ (\ text {E} _ \ text {Circle} \) is the point on the cycloalkyl ring set tree.

Therefore, a ring of trees DP answer is:
\ [\ {text} Ans = \ max \ {F (I) (0), G (J) (0) \} \]

\[ (i,j\in \text{E}_\text{Circle},i\neq j) \]

The figure below shows Luo Guqiu Camp courseware to explain:



The key code is as follows:

void covertree(int fr)//寻找基环树
{
 used[fr]=1;
 for(int i=head[fr];i;i=e[i].next)
 {
     int to=e[i].to;
     if(used[to]==0)
     {
         covertree(to);
     }
 }
}


void findcir(int fr,int fa)//寻找基环树中的环
{
 if(flag) return ;
 vis[fr]=1;
 for(int i=head[fr];i;i=e[i].next)
 {
     int to=e[i].to;
     if(vis[to]==0)
     {
         findcir(to,fr);
     }else if(to!=fa)
     {
         fri=fr;//第一个点
         toi=to;//第二个点
         E=i;//边的编号
         flag=1;
         return ;
     }
 }
}


void DPf(int fr)//以其中的一点为树根做树形DP
{
 visf[fr]=1;
 f[fr][1]=crit[fr];
 for(int i=head[fr];i;i=e[i].next)
 {
     int to=e[i].to;
     if(visf[to]==0&&(i^1)!=E)//保证不会选到第一个点和第二个点,相当于断边
     {
         DPf(to);
         f[fr][0]+=max(f[to][0],f[to][1]);
         f[fr][1]+=f[to][0];
     }
 }
}


void DPg(int fr)//再以另一点为树根再做一次树形DP
{
 visg[fr]=1;
 g[fr][1]=crit[fr];
 for(int i=head[fr];i;i=e[i].next)
 {
     int to=e[i].to;
     if(visg[to]==0&&(i^1)!=E)
     {
         DPg(to);
         g[fr][0]+=max(g[to][0],g[to][1]);
         g[fr][1]+=g[to][0];
     }
 }
}

for(int i=1;i<=n;i++)//调用+统计答案
{
 if(used[i]==1) continue;
 covertree(i);
 flag=0;
 findcir(i,-1);
 DPf(fri);
 DPg(toi);
 ans+=max(f[fri][0],g[toi][0]);
}

Special attention :

  • This title is a ring tree forest, rather than a single tree ring tree, look for it to be repeated covering ring tree, and finally all the answers together.

  • Due to the broken edge, so the star forward counter eimust be initialized to 1.

    • 用多个数组标记(used[],vis[],visf[],visg[])。
    • 一定要注意 f,gfr,to,不要手快打错了。

Guess you like

Origin www.cnblogs.com/nth-element/p/11785016.html