仙人掌树

文章目录

  • 普通仙人掌
    • 参考文献
    • 例题
    • 讲解
      • 构造圆方树
      • 圆方树的性质
      • 这道题目的解法
      • 代码
  • 广义仙人掌
    • 参考文献
    • 例题
    • 做法
    • 代码
    • 性质
  • 最后说

普通仙人掌

参考文献

奆佬YYB的博客 Orz:https://www.cnblogs.com/cjyyb/p/9098400.html

例题

题目

讲解

构造圆方树

这道题目其实就是在仙人掌上面求最近点对。

先说仙人掌的定义吧,每条边都最多在一个简单环上的图就是仙人掌。(简单环就是一个点双联通分量上点和边的数量是一样的)

好了,那么我们对于一个简单环,建立一个方点(原图上的点叫圆点),将环上的圆点全部连到方点上面,且对于原图中所有存在于点双联通的边全部删去,没有存在于连通分量的边保留,就成了这样:


那么如何证明他一定是个树呢。

两步证明,第一步证明其联通,第二步证明其 ∣ V ∣ − 1 = ∣ E ∣ |V|-1=|E| V1=E(边的数量是点的数量减一)。

摘自参考文献(注: S T S_T ST为方点, R T R_T RT为圆点):


不在环上的边在圆方树中依然存在,

因此这些边连通性不变;

每个环通过新建方点的方式连成一朵菊花,连通性不变。

因此圆方树是无向连通图。

原图中环的个数为 ∣ E ∣ − ∣ V ∣ + 1 |E|−|V|+1 EV+1,则
∣ V T ∣ = ∣ S T ∣ + ∣ R T ∣ = ∣ V ∣ + ∣ E ∣ − ∣ V ∣ + 1 = ∣ E ∣ + 1 , ∣ E T ∣ = ∣ E ∣ |V_T|=|S_T|+|R_T|=|V|+|E|−|V|+1=|E|+1,|E_T|=|E| VT=ST+RT=V+EV+1=E+1,ET=E

(大小为r 的环在仙人掌和圆方树中都是 r 条边),因此满足 ∣ V T ∣ = ∣ E T ∣ + 1 |V_T|=|E_T|+1 VT=ET+1


圆方树的性质

  1. 随便找个圆点为根,方点的父亲是圆点。
  2. 随便取一圆点为根,两个点在不断跳父亲的过程中,在相遇之前会跳动同一个环上且跳到的点都不是环上深度最小的点,那么他们的LCA为方点,反之,他们的LCA为圆点。
  3. 环中除深度最小的点以外其他点的父亲都是方点。

这道题目的解法

对于这道题目,建立完之后,我们该怎么做呢?

首先确定一个圆点为根,那么整个环中深度最浅的点我们称其为祖先节点 x x x,那么环上其他点与方点的边权就是到 x x x的最短距离,而方点到 x x x的边权为 0 0 0,然后跑LCA。

(以下认为即使他们跳到了一个环上,如果跳到的点是祖先节点,则不认为是跳到同一个环)根据第二个性质,如果LCA为圆点,那么他们不会经过同一个环,而经过不同的环时走方点的边权刚好就等价于在环上跑到环的父亲节点的最小距离,所以用一般树求距离的方法就行了,而对于LCA是方点来说,最多只会有一个相同的环(反正跑到了一个相同的环,在跳一次父亲就是同一个方点了),只要单独对环上这两个点求最短距离即可(至于求法吗,可以处理环上边权总和,然后让他们预处理朝同一个方向跑到祖先节点所经过的边的权值和,这样就可以在询问环上两个点的最小距离的时候 O ( 1 ) O(1) O(1)求了,当然,细节自己想),

代码

时间复杂度: O ( ( n + m ) log ⁡ n ) O((n+m)\log{n}) O((n+m)logn)

#include<cstdio>
#include<cstring>
#define  N  11000
#define  NN  21000
#define  M  25000
using  namespace  std;
inline  int  mymin(int  x,int  y){return  x<y?x:y;}
inline  int  zabs(int  x){return  x<0?-x:x;}
class  EDGE
{public:struct  node{int  y,next,c;}a[M];int  len,last[N];inline  void  ins(int  x,int  y,int  c){len++;a[len].y=y;a[len].c=c;a[len].next=last[x];last[x]=len;}
}a1,a2;
int  list[N],block,mdis[N]/*表示在环中全部超一个方向的dis*/,sum[N];//所有块的编号 
int  dfn[N],low[N],n,ti,di[N];
int  sta[N],top;
void  build(int  x,int  c)
{int  r=0;for(int  i=top;sta[i]!=x;i--)list[++r]=sta[i];list[++r]=x;//找到环上所有的点 block++;sum[block]=c+di[list[1]]-di[x];//建立分量编号以及边权总和 for(int  i=1;i<r;i++){int  y=list[i];mdis[y]=di[y]-di[x];a2.ins(block+n,y,mymin(sum[block]-mdis[y],mdis[y]));//构建圆方树 }a2.ins(x,block+n,0);
}
void  dfs1(int  x,int  fa)//强连通 
{sta[++top]=x;dfn[x]=low[x]=++ti;for(int  k=a1.last[x];k;k=a1.a[k].next){int  y=a1.a[k].y;if(y!=fa){if(!dfn[y])di[y]=di[x]+a1.a[k].c,dfs1(y,x),low[x]=mymin(low[x],low[y]);else  if(dfn[y]<dfn[x]/*与祖先形成分量*/)low[x]=dfn[y],build(y,a1.a[k].c);}}if(low[x]==dfn[x])a2.ins(fa,x,di[x]-di[fa]);//其是割点且不与其父亲在一个分量上,保留此边 top--;
}int  fa[NN][18],dis[NN]/*到根节点的距离*/,dep[NN]/*层数*/;
void  dfs2(int  x)//求LCA 
{for(int  i=1;i<=15;i++){fa[x][i]=fa[fa[x][i-1]][i-1];if(!fa[x][i])break;}for(int  k=a2.last[x];k;k=a2.a[k].next){int  y=a2.a[k].y;dis[y]=dis[x]+a2.a[k].c;fa[y][0]=x;dep[y]=dep[x]+1;dfs2(y);}
}
inline  int  diss(int  x,int  y)//求两个点的距离 
{if(dep[x]>dep[y])x^=y^=x^=y;int  ans=0,tx=x,ty=y;for(int  i=15;i>=0;i--){if(dep[fa[y][i]]>=dep[x])y=fa[y][i];}if(x==y)return  dis[ty]-dis[y];//直接相遇 for(int  i=15;i>=0;i--){if(fa[y][i]!=fa[x][i])x=fa[x][i],y=fa[y][i];}if(fa[x][0]>n)//方点的情况 {int  shit=zabs(mdis[x]-mdis[y]);return  dis[tx]+dis[ty]-dis[x]-dis[y]+mymin(shit,sum[fa[x][0]-n]-shit);}else  return  dis[tx]+dis[ty]-2*dis[fa[x][0]];
}
int  m,q;
int  main()
{dep[0]=-1;scanf("%d%d%d",&n,&m,&q);for(int  i=1;i<=m;i++){int  x,y,c;scanf("%d%d%d",&x,&y,&c);a1.ins(x,y,c);a1.ins(y,x,c);}dfs1(1,0);dfs2(1);for(int  i=1;i<=q;i++){int  x,y;scanf("%d%d",&x,&y);printf("%d\n",diss(x,y));}return  0;
}

广义仙人掌

参考文献

https://www.cnblogs.com/cjyyb/p/9098400.html

例题

[BeiJing2013]压力
时间限制:10s      空间限制:128MB题目描述
如今,路由器和交换机构建起了互联网的骨架。处在互联网的骨干位置的
核心路由器典型的要处理100Gbit/s的网络流量。他们每天都生活在巨大的压力
之下。
小强建立了一个模型。这世界上有N个网络设备,他们之间有M个双向的
链接。这个世界是连通的。在一段时间里,有Q个数据包要从一个网络设备发
送到另一个网络设备。
一个网络设备承受的压力有多大呢?很显然,这取决于Q个数据包各自走
的路径。不过,某些数据包无论走什么路径都不可避免的要通过某些网络设
备。
你要计算:对每个网络设备,必须通过(包括起点、终点)他的数据包有
多少个?
输入格式
第一行包含3个由空格隔开的正整数N,M,Q。
接下来M行,每行两个整数u,v,表示第u个网络设备(从1开始编号)和
第v个网络设备之间有一个链接。u不会等于v。两个网络设备之间可能有多个
链接。
接下来Q行,每行两个整数p,q,表示第p个网络设备向第q个网络设备发
送了一个数据包。p不会等于q。
输出格式
输出N行,每行1个整数,表示必须通过某个网络设备的数据包的数量。
样例输入
4 4 2
1 2
1 3
2 3
1 4
4 2
4 3
样例输出
2
1
1
2
提示
【样例解释】
设备1、2、3之间两两有链接,4只和1有链接。4想向2和3各发送一个数据
包。显然,这两个数据包必须要经过它的起点、终点和1。
【数据规模和约定】
对于40%的数据,N,M,Q≤2000
对于60%的数据,N,M,Q≤40000
对于100%的数据,N≤100000,M,Q≤200000题目来源:BZOJ

什么,你说BZOJ炸了?

数据?

自己找

做法

SO,广义圆方树是什么?

其实就是对于一个点双新建一个点,点双中的所有点向他连边。

蒯张图:

但是这样会导致丢失边的信息,因此只能处理点双的信息,这个东西其实就是类似缩点的一个算法,但是对割点的需求会比较大。

不难发现,一个点双的必经点只有割点、起/终点,直接在圆方树上树上差分即可。

当然,惯例,证明他是一棵树。显然

  1. 连通性,点双都连在一个点上,连通性不变。
  2. 证明是一棵树,不是树就是环喽。
    不难发现,这棵树上严格圆点连方点(只有两个点也是一个点双),方点连圆点,因此存在环的话,一定是方点-圆点-方点-圆点…-方点,的这个一个环。
    又不难知道,只有割点才会连接两个及以上的方点,这些圆点就是割点,但是这种情况说明这些割点间存在一个简单环,所以这种情况不成立。(其实就是用了下面的性质2)

代码

#include<cstdio>
#include<cstring>
#define  N  110000
#define  NN  210000
#define  M  410000
using  namespace  std;
inline  int  mymin(int  x,int  y){return  x<y?x:y;}
inline  int  mymax(int  x,int  y){return  x>y?x:y;}
class  EDGE
{public:struct  node{int  y,next;}a[M];int  len,last[NN];void  ins(int  x,int  y){len++;a[len].y=y;a[len].next=last[x];last[x]=len;}
}a1,a2;
int  dfn[N],low[N],ti,n,m,q;
int  sta[N],top,cnt;
void  dfs(int  x)
{dfn[x]=low[x]=++ti;sta[++top]=x;for(int  k=a1.last[x];k;k=a1.a[k].next){int  y=a1.a[k].y;if(!dfn[y]){dfs(y);low[x]=mymin(low[x],low[y]);if(low[y]==dfn[x]){cnt++;while(sta[top]!=y)a2.ins(cnt+n,sta[top--]);top--;a2.ins(cnt+n,y);a2.ins(x,cnt+n);}}else  low[x]=mymin(dfn[y],low[x]);}
}
int  tot[NN];
void  dfs2(int  x)
{for(int  k=a2.last[x];k;k=a2.a[k].next){int  y=a2.a[k].y;dfs2(y);tot[x]+=tot[y];}
}
int  fa[NN][20],dep[NN];//17
void  dfs3(int  x)
{for(int  i=1;i<=17;i++){fa[x][i]=fa[fa[x][i-1]][i-1];if(!fa[x][i])break;}for(int  k=a2.last[x];k;k=a2.a[k].next){int  y=a2.a[k].y;fa[y][0]=x;dep[y]=dep[x]+1;dfs3(y);}
}
inline  int  lca(int  x,int  y)
{if(dep[x]>dep[y])x^=y^=x^=y;for(int  i=17;i>=0;i--){if(dep[fa[y][i]]>=dep[x])y=fa[y][i];}if(x==y)return  x;for(int  i=17;i>=0;i--){if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];}return  fa[x][0];
}
int  main()
{
//	freopen("1.in","r",stdin);
//	freopen("1.out","w",stdout); dep[0]=-1;scanf("%d%d%d",&n,&m,&q);for(int  i=1;i<=m;i++){int  x,y;scanf("%d%d",&x,&y);a1.ins(x,y);a1.ins(y,x);}dfs(1);dfs3(1);for(int  i=1;i<=q;i++){int  x,y;scanf("%d%d",&x,&y);int  z=lca(x,y);tot[x]++;tot[y]++;tot[z]--;tot[fa[z][0]]--;}dfs2(1);for(int  i=1;i<=n;i++)printf("%d\n",tot[i]);return  0;
}

性质

  1. 圆点只连方点,方点只连圆点
  2. 非割点度为1,割点度≥2,因此把一个点删掉,若树分成两个以上的联通块,这个点就是原图上的割点。(至于证明吗,自己想想就差不多知道了,因为如果你一个点只在一个点双中的话,删掉这个点,连通性不变啊,对应在树上也一样)

最后说

怎么说,2020CSP-S初赛后填的第一个坑

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/40592.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

BZOJ1023 [SHOI2008]cactus仙人掌图

标签&#xff1a;图论-仙人掌&#xff0c;DP-杂题 题目 题目传送门 Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路&#xff08;simple cycle&#xff09;里&#xff0c;我们就称这张图为仙人掌图&#xff08;cactus&#xff09;。所谓简单回路就是指…

牛客-紫魔法师(仙人掌染色-判奇环)

题目链接&#xff1a;https://ac.nowcoder.com/acm/contest/7016/F 博客园食用链接&#xff1a;https://www.cnblogs.com/lonely-wind-/p/13530156.html 题目描述 “サーヴァント、キャスター、Medea。”–紫魔法师 给出一棵仙人掌(每条边最多被包含于一个环&#xff0c;无自…

BZOJ4784 [Zjoi2017]仙人掌

标签&#xff1a;树形DP&#xff0c;tarjan&#xff0c;仙人掌 题目 题目传送门 Description 如果一个无自环无重边无向连通图的任意一条边最多属于一个简单环&#xff0c;我们就称之为仙人掌。所谓简单环即不经过重复的结点的环。 现在九条可怜手上有一张无自环无重边的…

如何绘制一组创意的仙人掌图标

创建新的项目文件 启动并在后台运行Illustrator&#xff0c;创建新文档&#xff08;文件>新建或Control-N&#xff09; 画板数量&#xff1a;1 宽度&#xff1a; 800像素 高度&#xff1a; 600像素 单位&#xff1a; 像素 进入“高级”选项卡&#xff1a; 色彩模式&a…

大量短信群发?不妨来看看这几个平台

最近在跟着公司一块做一个新的项目&#xff0c;刚好我做到注册登录的模块&#xff0c;一个需要短信群发的功能&#xff0c;没有过多的精力去写短信验证码模块&#xff0c;便找了几个比较好用的API短信接口平台&#xff1b;在这里给大家列举几个不同的平台&#xff0c;希望能帮到…

短信平台不知道怎么选?来看看这几个平台:

不少程序员在做项目的时候会碰上短信收发验证码的问题&#xff0c;通常来说解决方案有二&#xff0c;要么自己写一个验证码模块儿&#xff0c;要么去找短信平台。但自己写一个验证码模块是出了名的麻烦&#xff0c;而且会耗费掉不少时间&#xff0c;有着时间到不如优化下自己的…

【chatgpt代码系列】雷达转点云算法沟通记录

AI作为一个强大的生产力工具&#xff0c;怎么使用它才能快速结合我们自己的工作呢&#xff1f;下面是我的探索&#xff0c;目前来看&#xff0c;是可以代替百度谷歌等搜索引擎的一部分作用&#xff0c;加入到我的工作流当中。

重磅!openAI开放chatGPT模型APIgpt-3.5-turbo,成本直降90%!

ChatGPT API&#xff0c;千呼万唤终于来了。 chatGPT不仅开放 成本还直降90%&#xff01; 全新API基于“gpt-3.5-turbo”模型&#xff0c;其基础是支持ChatGPT的GPT 3.5模型&#xff0c;取代了此前的“text-davinci-003.”。这款名为“gpt-3.5-turbo”的模型&#xff0c;定价…

模型量化:PTQ + onnx

8 位线性量化的数学表达 将 32 位浮点(实数)模型转换为 8 位整数模型 F 32 S c a l e ∗ ( I i n t 8 − Z ) 量化公式&#xff1a; I i n t 8 F 32 S c a l e Z F_{32} Scale * (I_{int8}-Z)\\ 量化公式&#xff1a; I_{int8} \frac{F_{32}}{Scale} Z F32​Scale∗(Ii…

模型量化

https://zhuanlan.zhihu.com/p/132561405 模型量化是一种将浮点计算转成低比特定点计算的技术&#xff0c;可以有效的降低模型计算强度、参数大小和内存消耗&#xff0c;但往往带来巨大的精度损失。尤其是在极低比特(<4bit)、二值网络(1bit)、甚至将梯度进行量化时&#xf…

量化模型

量化模型&#xff08;Quantized Model&#xff09;是一种模型加速&#xff08;Model Acceleration&#xff09;方法的总称&#xff0c;包括二值化网络&#xff08;Binary Network&#xff09;、三值化网络&#xff08;Ternary Network&#xff09;&#xff0c;深度压缩&#xf…

读取锁信息失败(8):该账户当前被锁定,所以用户 ‘sa‘ 登录失败。

读取锁信息失败(8)&#xff1a;该账户当前被锁定&#xff0c;所以用户 sa 登录失败。系统管理员无法将该账户解锁。 State:37000,Native:18486,Origin:[Microsoft][ODBC SQL Server Driver][SQL Server] 打开软件提示上面的信息 此问题是由于sa账户在同一时间被多次登录&#x…

Oracle连接账户被锁:the account is locked 的解决办法

Oracle连接账户被锁&#xff1a;the account is locked 问题背景 在做配置文件数据库密码加密时&#xff0c;没注意做了一些骚操作&#xff0c;导致数据库被锁&#xff0c;网上找的资料都试了个遍&#xff0c;还是没用。浪费了两三个小时&#xff0c;差点都卸载重装数据库了。…

oracle提示“记录被另外一个用户锁定“

问题描述&#xff1a; 某人对某一条数据进行了修改&#xff0c;oracle会通过这个事务记住这条数据&#xff0c;若修改的人没有进行提交或进行回滚记录&#xff0c;oracle是不允许对这条数据在此进行修改的&#xff0c;在这种情况下你要进行修改数据&#xff0c;则会被阻止&…

ORACLE数据库 某用户账户被锁定问题解决

遇到的问题&#xff1a; [realestate][ERROR] [2022-05-17 14:27:11] com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(2469) | create connection SQLException, url: jdbc:p6spy:oracle:thin:172.18.13.83:1521/orclxj, errorCode 28000, state 99999 j…

Oracle账户被锁定后如何解锁

**原因&#xff1a;** 今天拉取了新的代码后&#xff0c;由于oracle数据库的配置忘记了更改&#xff0c;启动项目时一直连接不上数据库&#xff0c;改了两次后还是连接不上&#xff0c;最后只能启动一下没拉取代码前的项目&#xff0c;发现报了一个账户被锁定 ![在这里插入图片…

【饭谈】坚守自己的职业规划,给自己留一张底牌吧。

最近想必大家都被新出的chatGPT吓坏了吧&#xff1f;各种机构和博主跟风似的疯狂说gpt多厉害&#xff0c;会取代多少人&#xff0c;导致多少人下岗&#xff0c;各种Ai测试兴起等贩卖焦虑的言论。获得了很多的流量&#xff0c;也变现了很多。但却给全行业的打工人带来了恐惧心理…

深度:从工业救国到数字化兴国!

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 昨天&#xff0c;发生了两件事情&#xff0c;一喜一悲&#xff0c;喜的是颁布了《数字中国建设整体布局规划》&#xff1b;悲的是“改革先锋”厉以宁先生离开了我们。将这两件事情结合起来&#xff0c;让我们思考一个问题—…

AI大模型,救了 “低代码” 的命

作者| Mr.K 编辑| Emma 来源| 技术领导力(ID&#xff1a;jishulingdaoli) 著名技术哲学家安德鲁•费恩伯格教授&#xff0c;曾提过一个很有创意的概念&#xff0c;“技术民主化”。教授认为&#xff0c;技术民主就是扩大社会个体的自由边界&#xff0c;让大家积极有效地参与到…

NVIDIA市值破万亿,回顾黄仁勋台大毕业典礼发表演说

夕小瑶科技说 分享 作者 | 黄仁勋 来源 | 芯榜、Datawhale干货 黄仁勋台大毕典演说全文。无论是追逐食物、或不被人当食物&#xff0c;你都要不停跑下去。 黄仁勋受邀参加台大毕业典礼。他出生于台南&#xff0c;4 岁时随家人离开台湾&#xff0c;前往美国。 摘要 英伟达&…