[XSY] 分割(dfs树)

分割
题目相当于问 删掉两个点后 图是否仍然连通
割点问题,考虑用dfs树解决
设删去点u,v(dfn[v]<dfn[u])
把 u, v 删去之后整棵树大概断成了几个部分:
• v 上面到根的部分,以及上面挂着的那些东西,记作 highhighhigh
• u 到 v 之间的那一段,以及上面挂着的那些东西,记作 midmidmid
• u ,v的子树们,记作 lowulow_ulowulowvlow_vlowv
在这里插入图片描述
要保证删去u,v后图连通,则lowulow_ulowumidmidmidlowvlow_vlowv必须想办法和highhighhigh连通

lowvlow_vlowv:每颗子树有非树边连接highhighhigh
lowulow_ulowu:每颗子树 有非树边连接highhighhigh 或 有非树边连接midmidmidmidmidmid有非树边连接highhighhigh
midmidmid:有非树边连接highhighhigh有非树边连接lowulow_ulowu的其中一颗子树,同时这颗子树有非树边连接highhighhigh

当然,fa[u]==vfa[u]==vfa[u]==v的情况略有不同,且v==1v==1v==1时要特判


上面的思路除了 加粗字体的情况 没考虑到,其它都想到了
以下是想不出来的实现:


对于 子树内有非树边连接highhighhigh 的条件:
预处理出 low[u] 表示 以u为根的子树通过非树边最高能连到的位置

对于 midmidmid有非树边连接highhighhigh 的条件:
预处理出 g[u][k] 表示 u到其2k2^k2k次祖先 的这一段以及上面挂着的东西中,不算 u,通过非树边最高能到的位置(树上倍增)
(注意:g[u][0]!=low[fa[u]],详见代码)

对于 lowulow_ulowu中有非树边连接midmidmid 的条件:
考虑转化一下条件,
原条件为 对于lowulow_ulowu的任意一颗子树,若在[1,dfn[v]-1]中没有通过非树边能连到的位置,那么在[dfn[v]+1,dfn[u]-1]中至少有一个通过非树边能连到的位置
我们将其转化为 lowulow_ulowu中有一颗子树在[1,dfn[v]-1]和[dfn[v]+1,dfn[u]-1]中均没有通过非树边能连到的位置,那么边(u,v)不能删
在这里插入图片描述
如图,w为u的其中一颗子树,标紫的点是w通过非树边能连到的位置中在u上方的部分,可以发现,只有v在low[w]及其往上的部分时,[1,dfn[v]-1]中才会没有w通过非树边能连到的位置,这时若[dfn[v]+1,dfn[u]-1]中没有其它w通过非树边能连到的位置,即dfn[w通过非树边第二高能连到的位置]>=dfn[u],则(u,v)不能删

预处理出 slow[u] 表示 以u为根的子树通过非树边第二高能连到的位置即可
(同学教的,妙啊!)

对于 midmidmid有非树边连接lowulow_ulowu的其中一颗子树,同时这颗子树有非树边连接highhighhigh 的条件:
还是考虑转化条件,
原条件为 lowulow_ulowu中有一颗子树,在[1,dfn[v]-1]和[dfn[v]+1,dfn[u]-1]中均有其通过非树边能连到的位置
转化为 对于lowulow_ulowu的其中一颗子树,记l,rl,rl,r为这棵子树通过非树边能连到的位置中在u上方部分的最高点和最低点,若 lll<=dfn[v]-1 且 rrr>=dfn[v]+1,即lll+1<=dfn[v]<=rrr-1,那么(u,v)边的midmidmid部分一定能通过连接这颗子树连到highhighhigh

具体地,lll即为low[son[u]],
对每个点u维护一个优先队列,记录以u为根的子树通过非树边能连到的位置,pop出 son[u] 的优先队列中 dfn值>=dfn[u] 的位置即可找到rrr(优先队列合并)


对于最后两个条件,我一开始想的是暴力维护每个点u即它的子树通过非树边能连到的所有位置(以dfn序为下标建线段树,维护区间内能连接到的位置的个数(类似权值线段树的感觉)),然后合并线段树
虽然后来了解到合并线段树的时间复杂度是O(nlogn)O(nlogn)O(nlogn),所以整道题的复杂度也就O(nlog2n)O(nlog^2n)O(nlog2n),即理论复杂度也是对的,但是常数过大,大概率会T

但是syh大佬通过把 判断对于确定的u,v,(u,v)是否可删 转化为 对于确定的u,寻找什么样的v满足(u,v) 可删/不可删,让这题有了简单许多的做法 OrzOrzOrz


Code:

#include<iostream>
#include<cstdio>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int N=3e5+5;
struct data{int v,nxt;
}edge[N<<1];
vector<int> vex[N],vid[N];
int n,m,cnt,head[N],ind,dfn[N],sz[N],son[N],fa[N][21];
int low[N],slow[N],g[N][21];
int st[N<<2];
int fl[N],hk[N];
//fl[u]=删掉u后,有几个u的子节点会被与连通图断开 
//hk[v]=删掉fa[v][0]后,v会与连通图断开 
map<int,int> mp[N];
//mp[a][b]=1表示为保持图连通,若删了a,则b不能被删 
bool fla[N],flagg[N];
int rt[N];
priority_queue<int> q[N];
queue<int> que;
void add(int u,int v){edge[++cnt].v=v;edge[cnt].nxt=head[u];head[u]=cnt;
}
void merge(int a,int b){int p[11];p[1]=low[a];p[2]=slow[a];p[3]=low[b];p[4]=slow[b];sort(p+1,p+5);low[a]=p[1];slow[a]=n+1;for(int i=2;i<=4;i++){if(p[i]!=p[i-1]){slow[a]=p[i];break;}}
}
inline void dfs(int u){ind++;dfn[u]=ind;for(int i=head[u];i;i=edge[i].nxt){if(!dfn[edge[i].v]){fa[edge[i].v][0]=u;dfs(edge[i].v);}    }
}
void dfs_tree(int u){//判low直接与high连通+low通过mid与high连通 sz[u]=1;low[u]=dfn[u];slow[u]=n+1;for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(v==fa[u][0]) continue;if(fa[v][0]==u){son[u]++;dfs_tree(v);merge(u,v);sz[u]=sz[u]+sz[v];if(low[v]>=dfn[u]){fl[u]++;hk[v]++;}else if(slow[v]>=dfn[u]) mp[u][low[v]]=1;}else{if(dfn[v]==low[u]) continue;if(low[u]>dfn[v]){slow[u]=low[u];low[u]=dfn[v];}else if(slow[u]>dfn[v]) slow[u]=dfn[v];}}
}
//此时的线段树用于统计low的最小值 
inline void update(int u,int l,int r,int x,int v){if(l>x||r<x)return;if(l==r){st[u]=v;return;}int mid=(l+r)/2;update(u<<1,l,mid,x,v);update(u<<1|1,mid+1,r,x,v);st[u]=min(st[u<<1],st[u<<1|1]);
}
inline int query(int u,int l,int r,int ql,int qr){if(l>qr||r<ql)return n+1;if(ql<=l&&r<=qr)return st[u];int mid=(l+r)/2;int res1=query(u<<1,l,mid,ql,qr);int res2=query(u<<1|1,mid+1,r,ql,qr);return min(res1,res2);
}
//此时的线段树用于维护区间是否可选 
inline void modify(int u,int l,int r,int ql,int qr){if(!flagg[u]){que.push(u);flagg[u]=1;}if(l>qr||r<ql)return;if(ql<=l&&r<=qr){st[u]=1;return;}int mid=(l+r)/2;modify(u<<1,l,mid,ql,qr);modify(u<<1|1,mid+1,r,ql,qr);st[u]=st[u<<1]&st[u<<1|1];
}
inline bool ask(int u,int l,int r,int x){if(l>x||r<x) return 0;if(st[u]) return st[u];if(l==r) return st[u];int mid=(l+r)/2;return ask(u<<1,l,mid,x)|ask(u<<1|1,mid+1,r,x);
}
inline void get_g(int u){//判mid不通过low直接与high连通  for(int i=1;i<=20;i++){fa[u][i]=fa[fa[u][i-1]][i-1];g[u][i]=min(g[u][i-1],g[fa[u][i-1]][i-1]);}int sum=0,tot=0,s=n+1;for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(v==fa[u][0]) continue;if(fa[v][0]==u) sum++;else s=min(s,dfn[v]);}for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(fa[v][0]==u){tot++;update(1,1,sum,tot,low[v]);}}tot=0;for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(fa[v][0]==u){tot++;g[v][0]=min(min(query(1,1,sum,1,tot-1),query(1,1,sum,tot+1,sum)),s);}}for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(fa[v][0]==u) get_g(v);}
}
int solve(int u,int v){int s=n+1;for(int i=20;i>=0;i--){if(dfn[fa[v][i]]>dfn[u]){s=min(s,g[v][i]);v=fa[v][i];}}return s;
}
int mergeq(int a,int b){if(q[a].size()<q[b].size()) swap(a,b);while(!q[b].empty()){q[a].push(q[b].top());q[b].pop();}return a;
}
inline void getans(int u){//判mid通过low与high连通 for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(fa[v][0]==u) getans(v);}	rt[u]=u;for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(v==fa[u][0])continue;if(fa[v][0]==u){int l=low[v],r=0;while(!q[rt[v]].empty()){if(q[rt[v]].top()>=dfn[u]) q[rt[v]].pop();else{r=q[rt[v]].top();break;}}modify(1,1,n,l+1,r-1);//对于非树边(u,y)(dfn[y]<dfn[u]),若dfn[y]在[l+1,r-1]的区间内,则删去此边后(u,y)边的mid部分仍与high连通 rt[u]=mergeq(rt[v],rt[u]);}else{q[rt[u]].push(dfn[v]);}}for(int i=0;i<vex[u].size();i++){int x=u;int y=vex[u][i];int z=vid[u][i];if(dfn[y]>dfn[x])continue;if(x==1||y==1)continue;if(y==fa[x][0])continue;if(!ask(1,1,n,dfn[y]))fla[z]=1;}while(!que.empty()){flagg[que.front()]=0;st[que.front()]=0;que.pop();}//恢复 
}
char check(int id,int a,int b){if(dfn[a]>dfn[b]) swap(a,b);if(a==1){if(fa[b][0]==a){if(son[a]>2) return '1';if(son[a]>1&&sz[b]>1) return '1';if(son[b]>1) return '1';return '0';}if(son[a]>1) return '1';if(mp[b][dfn[a]]==0&&fl[b]==0) return '0';return '1';}if(fa[b][0]==a){if(sz[b]==1&&hk[b]==1){if(fl[a]<=1&&fl[b]==0&&mp[b][dfn[a]]==0) return '0';}else{if(fl[a]==0&&fl[b]==0&&mp[b][dfn[a]]==0) return '0';}return '1';}if(fl[a]||fl[b]||mp[b][dfn[a]]) return '1';int s=solve(a,b);if(s>=dfn[a]&&fla[id]) return '1';return '0';
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);add(x,y);add(y,x);vex[x].push_back(y);vex[y].push_back(x);vid[x].push_back(i);vid[y].push_back(i);}dfs(1);dfs_tree(1);get_g(1);for(int i=1;i<=n*4;i++) st[i]=0;getans(1);for(int i=1;i<=m;i++)putchar(check(i,edge[i*2-1].v,edge[i*2].v));
}

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

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

相关文章

三分法讲解

二分用到的挺多&#xff0c;三分用的少&#xff0c;但也不能忘。。。 二分我们常常用于一个具有单调性的情况中求解某值 而三分就像是求一个凸性或凹形函数时&#xff0c;来求那个凹凸点 一开始L0&#xff0c;Rinf&#xff0c;然后也是不断缩小L与R的范围&#xff0c;逼近最值…

使用C#读写结构化的二进制文件

最近工作上遇到一个问题&#xff0c;就是有将近200万个CSV文件&#xff0c;每个CSV文件包含了成千上万条实验数据&#xff0c;CSV以一个不连续的整数值作为文件名&#xff0c;比如&#xff1a;1.CSV、2.CSV、3.CSV、5.CSV等等。另外又有200万个XML文件&#xff0c;每个XML文件的…

牛客IOI周赛16-普及组

比赛链接 文章目录求导题目描述题解&#xff1a;猜数题意&#xff1a;题解&#xff1a;方法一 贪心方法二 暴力答题卡题意&#xff1a;题解&#xff1a;代码&#xff1a;求导 链接&#xff1a; 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C …

Pipelines - .NET中的新IO API指引(二)

原文&#xff1a;Pipelines - a guided tour of the new IO API in .NET, part 2作者&#xff1a;marcgravell在上一章&#xff0c;我们讨论了以往的StreamAPI中存在的一些问题&#xff0c;并且介绍了Pipe,PipeWriter,PipeReader 等API&#xff0c;研究如何写出一个Pipe 并且从…

[XSY] 线图(树形DP、分类讨论)

线图 如图&#xff0c;每个L(L(T))上的点对应T上的一条三点链 在连接L(L(T))上两点&#xff0c;当且仅当两点代表的三点链在T上有共边&#xff0c;且边权为 共边边权*2非共边1边权非共边2边权 在L(L(T))上从点u走到点v&#xff0c;等价于u代表的三点链在T上删掉自己的一条边&…

牛客网【每日一题】4月29日题目精讲 Symmetric Matrix

链接&#xff1a; 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 524288K&#xff0c;其他语言1048576K 64bit IO Format: %lld题目描述 输入描述: The input consists of several test cases and is terminated by end-of-file. Each test c…

邻接矩阵和邻接表的使用

邻接矩阵和邻接表的使用 邻接矩阵 为了遍历一个图&#xff0c;我们使用了邻接矩阵&#xff0c;及用ai,ja_{i,j}ai,j​表示由a到b的边权 注&#xff1a;若这两个点不相连或ijijij&#xff0c;那么这个值就会设定为一个非正常的值&#xff0c;以便遍历时特判不走这条边 使用&am…

一个迄今为止最快的并发键值存储库FASTER诞生

FASTER在过去十年中&#xff0c;云中的数据密集型应用程序和服务有了巨大的增长。数据在各种边设施&#xff08;例如&#xff0c;设备&#xff0c;浏览器和服务器&#xff09;上创建&#xff0c;并由云应用程序处理用来获得数据价值或做出决策。应用程序和服务可以处理收集的数…

牛客网【每日一题】4月30日题目精讲 换个角度思考

链接&#xff1a; 文章目录题目描述题解&#xff1a;主席树做法&#xff1a;代码&#xff1a;树状数组&#xff1a;更扯淡的方法&#xff01;&#xff01;&#xff01;时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言…

三元环计数四元环计数

三元环计数 问题 给出一张n个点m条边的无向图&#xff0c;问图中有多少个三元组{ u , v , w } &#xff0c;满足图中存在 { (u,v) , (v,w) , (w,u) } 三条边。 求解 Step1 定向 将所有点按 度数 从小到大排序&#xff0c;如果度数相同按 点编号 从小到大排序&#xff0c;u…

牛客网【每日一题】5月1日题目 [SCOI2012]滑雪与时间胶囊

链接&#xff1a; 时间限制&#xff1a;C/C 2秒&#xff0c;其他语言4秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld题目描述 a180285非常喜欢滑雪。他来到一座雪山&#xff0c;这里分布着M条供滑行的轨道和N个轨道之间的交点&#x…

漫谈单体架构与微服务架构(上):单体架构

最近微服务架构特别火爆&#xff0c;就跟人工智能、区块链一样&#xff0c;软件架构设计如果不提微服务&#xff0c;感觉就像是与世界先进的架构风格和开发技术脱了节似的&#xff0c;各方各面都无法彰显高大上的气质。本来再打算使用一套系列文章来讨论微服务的方方面面&#…

ASP.NET Core应用程序的参数配置及使用

应用程序的开发不仅仅是写代码这点事情。假设你正在开发一个能够支持多次部署的微服务&#xff0c;此时你就需要有一个合理的应用程序配置方案&#xff0c;以便在开发和生产环境中能够方便地选用不同的配置参数&#xff0c;并且能够在部署到容器服务&#xff08;比如ACS或者Kub…

“Shopee杯” e起来编程暨武汉大学2020年大学生程序设计大赛决赛(重现赛)

比赛链接 文章目录A题 A Simple Problem about election题目描述题解&#xff1a;代码&#xff1a;D题 Deploy the medical team题意&#xff1a;题解&#xff1a;代码&#xff1a;F题 Figure out the sequence题意&#xff1a;题解&#xff1a;代码A题 A Simple Problem about…

RabbitMQ一个简单可靠的方案(.Net Core实现)

前言最近需要使用到消息队列相关技术&#xff0c;于是重新接触RabbitMQ。其中遇到了不少可靠性方面的问题&#xff0c;归纳了一下&#xff0c;大概有以下几种&#xff1a;1. 临时异常&#xff0c;如数据库网络闪断、http请求临时失效等&#xff1b;2. 时序异常&#xff0c;如A任…

牛牛染颜色

链接&#xff1a; 文章目录题目描述题意&#xff1a;题解&#xff1a;核心代码&#xff1a;时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 131072K&#xff0c;其他语言262144K 64bit IO Format: %lld题目描述 牛牛最近得到了一颗树&#xff0…

.netcore consul实现服务注册与发现-单节点部署

一、Consul的基础介绍Consul是HashiCorp公司推出的开源工具&#xff0c;用于实现分布式系统的服务发现与配置。与其他分布式服务注册与发现的方案&#xff0c;比如 Airbnb的SmartStack等相比&#xff0c;Consul的方案更“一站式”&#xff0c;内置了服务注册与发现框 架、分布一…

分布式事务解决方案以及 .Net Core 下的实现(上)

数据一致性是构建业务系统需要考虑的重要问题 &#xff0c; 以往我们是依靠数据库来保证数据的一致性。但是在微服务架构以及分布式环境下实现数据一致性是一个很有挑战的的问题。最近在研究分布式事物&#xff0c;分布式的解决方案有很多解决方案&#xff0c;也让我在研究的同…

微软MVP张善友告诉你,微服务选型要注意这些地方

周六的下午&#xff0c;广州周大福金融中心的写字楼静悄悄的&#xff0c;53楼的实盈多功能会议室却异常火爆&#xff0c;热闹非凡。来自广州各大科技公司的技术小伙伴们齐聚一堂&#xff0c;他们都在期待着一个人&#xff0c;那就是——微软MVP张善友和他带来的 .NET Core 微服…

像鱼

链接&#xff1a; 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld题目描述 给你一个边长为 n 的用硬币摆成的实心三角形&#xff0c;请问把他倒过来最少需要多少步&#xff1f; 例子…