Loading

2607-骑士

基环树上的dp。

题目给出的图是一个一个所有点的出度为一的有向图,这样的图可以形成多棵基环内向树。要求在树上选一些不相邻的点,让他们的点权和最大。

发现在图是一棵树的情况下这题就是经典题没有上司的舞会,考虑把基环树边拆成树,由于题目的构造方法,每一个弱联通块内最多只有一个环。那么可以把这个环拆一条边,分别设定两个节点不选,进行两遍树形dp取最大值即可。

实际写的时候有挺多坑的。。

  • 判断弱联通块的环:可以补成无向图跑Tarjan判环,但是要特判二元环的情况。用并查集相对比较简单,可行性证明:因为这里一个弱联通块最多只有一个环。
  • 注意写法:
void dfs(int now){
	if(vis[now]) return;
  //...
}
void dfs(int now){
  //...
  for(){
    if(vis[v]) continue;
    dfs(v);
    dp[now]=//...
  }
}

第一种写法在二元环的情况下补成的无向图会有重边,会重复加上两遍dp[v]的贡献。

  • 类似的,判断
if(v==node1&&u==node2||(v==node2&&u==node1)) continue;

在二元环的情况下不能通过二元环去到另一个节点。

posted @ 2021-09-15 21:28  14long  阅读(38)  评论(0)    收藏  举报