题目大意

给定一棵基环外向树,和若干组询问,对于每次独立的询问都指定一些起点和一些终点,你删去一些边,使得从任意起点出发都无法到达终点,并让删去的边的编号的最小值最大,求这个最大的最小值。

题解

不难发现,在基环外向树中,任意两个点之间至多有唯一条简单路径,且对于这道题来讲非简单路径是没有意义的,因为非简单路径一定会囊括一个简单路径。这意味着对于每一个终点,至多有一个与之对应的距离最短的起点,使得当你将这条路径上某一条边删掉时,这个起点就不可能被到达了。那么我们显然会贪心的删去路径上编号最大的那一条。由于每一个点的入边(如果有的话)是唯一的,且没有修改操作,我们就可以用倍增来求路径最大值。

现在问题就转化为如何找每个重点对应的起点,我们分开考虑。

先考虑起点仅通过树边到达终点的情况。这个比较好办,将所有起点按照深度从小到大依次处理,每次把当前起点的深度当做标记覆盖到以这一起点所代表的的子树中,这个用线段树处理即可。做完这件事以后,扫一遍终点,如果它已经被覆盖到了,那么就通过标记和深度直接算出起点和终点的距离,倍增求一下最大值,最终答案取$\min$,然后把这个终点删掉即可。

剩下的终点一定满足没有一个起点能够仅通过树边到达,所以必须通过一部分环上的边,因而不在环上的起点也没用了,删掉即可。我们直接让剩下的终点先跳到它们所在的树的树根上,并在路径上的边求编号的$\max$,如果树根不在环上或树根所在的环上没有任何起点,那么这个中点本身就不可被任何起点到达,对答案没有贡献。然后对于每一个环,将起点和终点都按照顺时针排序,枚举每一个终点都一定能找到它的前驱起点,更新答案即可。

复杂度$O(N+\sum\limits_{i=1}^{m} (t_i+f_i)\log N)$

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define M 200020
#define mid ((l+r)>>1)
using namespace std;
const int BufferSize=1<<19;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
} return *head++;
}
int read(){
int nm=0,fh=1; char cw=Getchar();
for(;!isdigit(cw);cw=Getchar()) if(cw=='-') fh=-fh;
for(;isdigit(cw);cw=Getchar()) nm=nm*10+(cw-'0');
return nm*fh;
}
int n,m,fs[M],fa[M][19],t[M][19],tmp=1,dfn[M],sz[M],od[M],to[M],nt[M];
int cnt,id[M],dep[M],tg[M<<2],maxn,tp[M],CT[M];
int S1[M],S2[M],C1[M],C2[M];
bool cir[M],vis[M],ist[M];
void link(int x,int y){nt[tmp]=fs[x],fs[x]=tmp,to[tmp++]=y;}
void dfs(int x){
sz[x]=1,dfn[x]=++cnt,vis[x]=true;
for(int i=fs[x];i!=-1;i=nt[i]){
if(cir[to[i]]) continue; id[to[i]]=id[x];
dep[to[i]]=dep[x]+1,tp[to[i]]=tp[x];
dfs(to[i]),sz[x]+=sz[to[i]];
}
}
bool cmpd(int x,int y){return dep[x]<dep[y];}
bool cmpc(int x,int y){if(id[tp[x]]!=id[tp[y]]) return id[tp[x]]<id[tp[y]];return od[tp[x]]>od[tp[y]];}
void pushdown(int x){if(tg[x]!=-1) tg[x<<1]=tg[x<<1|1]=tg[x],tg[x]=-1;}
void upd(int x,int l,int r,int L,int R,int D){
if(r<L||R<l) return;
if(L<=l&&r<=R){tg[x]=D;return;}
pushdown(x),upd(x<<1,l,mid,L,R,D),upd(x<<1|1,mid+1,r,L,R,D);
}
int qry(int x,int l,int r,int pos){
if(l==r) return tg[x]; pushdown(x);
if(pos<=mid) return qry(x<<1,l,mid,pos); return qry(x<<1|1,mid+1,r,pos);
}
int dp(int x,int dt){
int res=0;
for(int k=0;dt>0;k++,dt>>=1) if(dt&1) res=max(res,t[x][k]),x=fa[x][k];
return !res?m+1:res;
}
int main(){
n=read(),m=read(),memset(fs,-1,sizeof(fs));
for(int i=1;i<=m;i++){int u=read(),v=read();fa[v][0]=u,t[v][0]=i,link(u,v);}
for(int i=1;i<=n;i++){
if(vis[i]) continue; int now;
for(vis[now=i]=true;fa[now][0]&&!vis[fa[now][0]];now=fa[now][0]) vis[fa[now][0]]=true;
if(!fa[now][0]){
ist[now]=true,t[now][0]=0;
id[now]=++maxn,tp[now]=now,dfs(now); continue;
}
for(maxn++;!cir[now];now=fa[now][0]){
cir[now]=true,id[now]=maxn,tp[now]=now;
od[fa[now][0]]=od[now]+1,CT[maxn]++;
} dfs(now);
for(now=fa[now][0];od[now]!=CT[maxn];now=fa[now][0]) dfs(now);
}
for(int k=1;k<19;k++){
for(int i=1;i<=n;i++){
fa[i][k]=fa[fa[i][k-1]][k-1];
t[i][k]=max(t[i][k-1],t[fa[i][k-1]][k-1]);
}
}
for(int Qs=read();Qs;--Qs){
upd(1,1,n,1,n,-2);
int now,m1=read(),m2,st=1,ed=1,ans=m+1,n1=0,n2=0,ps=1;
for(int i=1;i<=m1;i++) S1[i]=read(); m2=read();
for(int i=1;i<=m2;i++) S2[i]=read(); sort(S1+1,S1+m1+1,cmpd);
for(int i=1;i<=m1;i++) upd(1,1,n,dfn[S1[i]],dfn[S1[i]]+sz[S1[i]]-1,dep[S1[i]]);
for(int i=1;i<=m2;i++){
if(!dep[S2[i]]){if(cir[tp[S2[i]]]) C2[++n2]=S2[i];continue;}
int num=qry(1,1,n,dfn[S2[i]]),cst;
if(num>=0) cst=dp(S2[i],dep[S2[i]]-num),ans=min(ans,cst);
else C2[++n2]=S2[i];
}
for(int i=1;i<=m1;i++) if(cir[S1[i]]) C1[++n1]=S1[i];
sort(C1+1,C1+n1+1,cmpc),sort(C2+1,C2+n2+1,cmpc),C1[n1+1]=C2[n2+1]=0;
for(int i=1;i<=n2;i++){
while(ed<n1&&id[C1[st]]<id[tp[C2[i]]]) st=ed+1,ed=ps=st;
if(id[C1[st]]<id[tp[C2[i]]]) break;
if(id[C1[st]]>id[tp[C2[i]]]) continue;
while(ed<n1&&id[C1[st]]==id[C1[ed+1]]) ed++;
now=cir[C2[i]]?0:dp(C2[i],dep[C2[i]]),C2[i]=tp[C2[i]];
while(ps<ed&&od[C1[ps+1]]>od[C2[i]]) ps++;
if(od[C1[ps]]>od[C2[i]]) now=max(now,dp(C2[i],od[C1[ps]]-od[C2[i]]));
else now=max(now,dp(C2[i],CT[id[C1[ps]]]+od[C1[ed]]-od[C2[i]]));
if(now) ans=min(ans,now);
}
if(ans==m+1) puts("OK"); else printf("%d\n",ans);
}
return 0;
}

  

Statement的更多相关文章

  1. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):

    org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): da.huying.usermanag ...

  2. [解决方案]CREATE DATABASE statement not allowed within multi-statement transaction.

    CREATE DATABASE statement not allowed within multi-statement transaction. 刚开始报这个错误的时候,我上度娘搜了一下. 别人是在 ...

  3. Drop all the tables, stored procedures, triggers, constraints and all the dependencies in one SQL statement

    Is there any way in which I can clean a database in SQl Server 2005 by dropping all the tables and d ...

  4. JDBC中的Statement和PreparedStatement的区别

    JDBC中的Statement和PreparedStatement的区别  

  5. SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT'OpenRowset/OpenDatasource' 的访问

    delphi ado 跨数据库访问 语句如下 ' and db = '帐套1' 报错内容是:SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATE ...

  6. Exception:HTTP Status 500 - org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)

    主要错误信息如下: HTTP Status 500 - org.apache.ibatis.binding.BindingException: Invalid bound statement (not ...

  7. SQL SERVER 2005删除维护作业报错:The DELETE statement conflicted with the REFERENCE constraint "FK_subplan_job_id"

    案例环境: 数据库版本: Microsoft SQL Server 2005 (Microsoft SQL Server 2005 - 9.00.5000.00 (X64) ) 案例介绍: 对一个数据 ...

  8. 第1章 重构,第一个案例(2):分解并重组statement函数

    2. 分解并重组statement (1)提炼switch语句到独立函数(amountFor)和注意事项. ①先找出函数内的局部变量和参数:each和thisAmount,前者在switch语句内未被 ...

  9. 第1章 重构,第一个案例(1):糟糕的statement函数设计

    1. 启航:影片出租,计算每一位顾客的消费金额并打印清单 1.1 场景说明: (1)影片分类规则:普通片.儿童片和新片等3类 (2)每种影片计算租金的方式. ①普通片:基本租金为2元,超过2天的部分每 ...

  10. jdbc执行Statement接口的步骤

    jdbc执行Statement接口的步骤如下: 1)驱动注册程序: Class.forName(com.mysql.jdbc.Driver); 2)获取连接对象: Connection conn = ...

随机推荐

  1. 第6章 网页解析器和BeautifulSoup第三方插件

    第一节 网页解析器简介作用:从网页中提取有价值数据的工具python有哪几种网页解析器?其实就是解析HTML页面正则表达式:模糊匹配结构化解析-DOM树:html.parserBeautiful So ...

  2. jquery实现全选、全消、反选功能

    HTML代码: <input type="checkbox" name="checkbox" class="A" /> 使用按钮 ...

  3. python 基础 9.6 设计表结构

    一. 设计表结构    在操作设计数据库之前,我们先要设计数据库表结构,我们就来分析分析经典的学生,课程,成绩,老师这几者他们之间的关系,我们先来分析各个主体他们直接有什么属性,并确定表结构,在实际开 ...

  4. EasyDarwin开源流媒体服务器Golang版本:拉转推功能之拉流实现方法

    EasyDarwin开源流媒体服务器(www.easydarwin.org),拉转推是一个很有意义的功能,它可将一个独立的RTSP数据源"拉"到服务器,再通过转发协议转发给多个客户 ...

  5. Zookeeper数据与存储

    一.前言 前面分析了Zookeeper对请求的处理,本篇博文接着分析Zookeeper中如何对底层数据进行存储,数据存储被分为内存数据存储于磁盘数据存储. 二.数据与存储 2.1 内存数据 Zooke ...

  6. 【python】-- Socket粘包问题 ,解决粘包的几种方法、socket文件下载,md5值检验

    上一篇随笔:“socket 接收大数据”,在win系统上能够运行,并且解决了大数据量的数据传输出现的问题,但是运行在linux系统上就会出现如下图所示的情况: 就是服务端两次发送给客户端的数据(第一次 ...

  7. Django 之restframework1

    Restframework 这里先简单的介绍一下restful协议 ----一切皆是资源,操作只是请求方式 基于restful协议的框架有很多Django下的restframework只是其中的一种 ...

  8. Linux踢出已登录用户

    1.使用w命令可以查看当前登录系统的所有用户 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root tty1 - 08:05 4:29 0.09s 0.09s - ...

  9. go语言之接口一

    在Go语言中,一个类只需要实现了接口要求的所有函数,我们就说这个类实现了该接口 我们定义了一个File类,并实现有Read().Write().Seek().Close()等方法.设 想我们有如下接口 ...

  10. 几款Java常用基础工具库

    通用工具类(字符串.时间格式化.BeanUtils.IO) 1. commons-lang3库 1.1. org.apache.commons.lang3.StringUtils类 日常代码中,我们经 ...