首页 > 其他分享 >骑士:基环树

骑士:基环树

时间:2023-10-05 17:56:08浏览次数:38  
标签:rt int LL ne long 基环树 骑士 include

https://www.bilibili.com/video/BV1Aa411Q7qp/?spm_id_from=333.999.0.0&vd_source=23dc8e19d485a6ac47f03f6520fb15c2

董老师讲的很清楚

https://www.luogu.com.cn/problem/P2607

 思路:

1、深搜找环

2、断环成树,对树深搜计算(断边:标记端点或者标记边)

O(N)

单向边:

// Luogu P2607 [ZJOI2008] 骑士
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e6+10;
typedef long long LL;
int n;
struct edge{int v,ne;}e[N];
int h[N],w[N],idx;
int r1,r2,vis[N];
LL f[N][2],sum;

void add(int a,int b){
  e[++idx]={b,h[a]};
  h[a]=idx;
}
void find(int u,int rt){//找两个根
  vis[u]=1;
  for(int i=h[u];i;i=e[i].ne){
    int v=e[i].v;
    if(v==rt){r1=u,r2=v;return;}
    if(vis[v])continue;
    find(v,rt);
  }
}
LL dfs(int u,int rt){//树上DP
  f[u][0]=0; f[u][1]=w[u];
  for(int i=h[u];i;i=e[i].ne){
    int v=e[i].v;
    if(v==rt)continue;
    dfs(v,rt);
    f[u][0]+=max(f[v][0],f[v][1]);
    f[u][1]+=f[v][0];
  }
  return f[u][0];
}
int main(){
  scanf("%d",&n);
  for(int v=1,u;v<=n;v++){
    scanf("%d%d",&w[v],&u);
    add(u,v);//单向边
  }
  for(int i=1;i<=n;i++){
    if(!vis[i]){
      r1=r2=0;
      find(i,i);
      if(r1){
        LL res1=dfs(r1,r1);
        LL res2=dfs(r2,r2);
        sum+=max(res1,res2);
      }
    }
  }
  printf("%lld",sum);
  return 0;
}

  

双向边:

// Luogu P2607 [ZJOI2008] 骑士
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e6+10;
typedef long long LL;
int n;
struct edge{int v,ne;}e[N<<1];
int h[N],w[N],idx=1;
int r1,r2,vis[N],be[N<<1];
LL f[N][2],sum;

void add(int a,int b){
  e[++idx]={b,h[a]};h[a]=idx;
}
bool find(int u,int ine){
    vis[u]=true;
    for(int i=h[u];i;i=e[i].ne){
      if(i==(ine^1))continue;
        int v=e[i].v;
        if(!vis[v]){//v尚未访问
            if(find(v,i)) return 1;
        } else{//v已访问
      r1=u,r2=v,be[i]=1,be[i^1]=1;
      return 1;
        }
    }
    return 0;
}
LL dfs(int u,int ine){//树上DP
  vis[u]=true;f[u][0]=0;f[u][1]=w[u];
  for(int i=h[u];i;i=e[i].ne){
    if(i==(ine^1)||be[i])continue;
    int v=e[i].v;
    dfs(v,i);
    f[u][0]+=max(f[v][0],f[v][1]);
    f[u][1]+=f[v][0];
  }
  return f[u][0];
}
int main(){
  scanf("%d",&n);
  for(int v=1,u;v<=n;v++){
    scanf("%d%d",&w[v],&u);
    add(u,v);add(v,u);
  }
  for(int i=1;i<=n;i++){
    if(!vis[i]){
      r1=r2=0;
      find(i,0);
      if(r1){
        LL res1=dfs(r1,0);
        LL res2=dfs(r2,0);
        sum+=max(res1,res2);
      }
    }
  }
  printf("%lld",sum);
  return 0;
}

  

标签:rt,int,LL,ne,long,基环树,骑士,include
From: https://www.cnblogs.com/shirlybaby/p/17743693.html

相关文章

  • 【基环树 | 题解】P5022 [NOIP2018 提高组] 旅行
    前言一日知基环树弱,固补题。关于基环树基环树定义一个环,环上每个点都有一颗以该点为根的树,如下图为一棵基环树关于基环树常规思路通常来说基环树常规思路是先处理环上树的结果,后通过树的结果来处理换上结果。具体处理方式依照题目来定。然而只是通常来说因为基环树的问......
  • 10.4 国庆 环形dp与基环树笔记
    1.知识点环形dp环形dp的概念•环形dp与基环树在许多环形结构的问题中,我们可以在环中从某个位置把环断开,把这个环变成线性的,然后进行\(dp\)等操作。•把能通过上述操作解决的环形问题称作"可拆解的环形问题"。环形dp的两种策略•第一次在任意位置把环断开成链,按照......
  • LeetCode 周赛上分之旅 #49 再探内向基环树
    ⭐️本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]和BaguTreePro知识星球提问。学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场LeetCode周赛的解题报告,一......
  • 【学习笔记】(28) 基环树
    首先,严格地讲,基环树不是树,它是一张有\(n\)个节点、\(n\)条边的图。介绍无向图上的基环树有向图上的基环树内向树出度为1外向树入度为1流程找到唯一的环;对环之外的部分按照若干棵树处理;考虑与环一起计算。找环从任意一点开始搜索;每次拓展到的点涂为灰色,回......
  • hdu 1372 Knight Moves 骑士的移动 bfs--马走日
    #include<stdio.h>#include<string.h>#include<queue>usingnamespacestd;charss[3],ee[3];intx1,y1,x2,y2;structpos{intx,y,step;}sta,end;intf[10][10];intdir[8][2]={1,2,1,-2,-1,2,-1,-2,2,1,2,-1,-2,1,-2,-1};boolfan......
  • P4042 [AHOI2014/JSOI2014] 骑士游戏
    原题非常好的一道题,用到了一个重要的思路:消除\(dp\)的后效性不要觉得这个东西很恐怖,其实这个东西并不复杂,只是名字有点吓人我们容易想到对把原题抽象成一个图,我们容易想到如果该图为\(DAG\)我们要怎么做,直接拓扑上\(dp\)即可但回到原题,我们发现\(dp\)就有了一些问题:这个题是有......
  • 基环树问题 解题报告
    luoguP5022旅行题意对于60%的数据,给一棵树,求一条字典序最小的Hamilton路径;对于40%的数据,给一颗基环树,求一条字典序最小的Hamilton路径。分析前向星存图,对于每个点的出边排序,从1开始dfs一遍即可过60%数据;对于基环树,由于Hamilton路径在树上必然有一条边不经过,而这条边必然......
  • 黑魂231 黑骑士建模
    把素材里的c2410材料导入unity项目的model文件夹里,用一个文件夹放起来。然后把c2410模型放进EnemyHandle里,取消ybot。接着将c2410的material的材质包都选上,里面的shader改成有Specularsetup的选项。把对应的材质原图和光影图放进去。 把贴图和法线素材放进Textures文件夹......
  • 代码源 - 基环树
    ZJOI2008骑士自己写的时候建的是\(dls\)的反图,想的是基环树不是要保证每个点的出度为\(1\),就选择每个点向仇恨点连接一条有向边.这种情况下如果记录每一个点出度指向哪,那么在找环的时候不一定能找到,因为图上带环的话要根据入度点找环(画图理解)如果记录入度......
  • 【题解】Luogu[P2607] [ZJOI2008] 骑士
    题目说给定\(n\)个点\(n\)个关系,也就是\(n\)条边,显然是基环树,又因为没有规定一定连通,于是我们可以将题目简化为给定一个基环树森林,点有点权,相邻的两个点不能同时选,问最大点权和。part1我们先考虑如果没有环,只是树,该怎么做。这一部分很简单,令\(f_{i,0/1}\)表示以\(i\)......