思路:tarjan把桥找出来,然后缩点,注意这里的缩点是:如果两个点之间的连边不是桥,那么就把他们缩起来,然后用一个lct维护,对于每个询问,如果官道连接的是两个联通块的话,就把他们连起来,否则我们就把u到v的路径全部染色成0

最后只要询问缩点完的S到缩点完的T的路径上有多少是1就是答案了,最后复杂度:O(nlogn)

至于为什么这么做:因为我们要找必经过的边,这不就是桥吗,那我们先预处理出原来图的桥,然后把图转变成树,之后对于官道来说,它只要是连接了两个在同一个联通块里的点,就表明这段路绝对不可能是必经之路,而对于连接两个连通分量的边,那么它就是新的桥啊!因此它要被新建成为lct中的一条边。

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
struct edge{
int u,v;
}e[];
int n,m;
int tot,go[],next[],first[],Id[];
int ch[][],sz,num,sum[],w[],col[],tag[];
int dfn[],low[],pd[],vis[];
int st[],c[],belong[],fa[];
int rev[],size[];
int read(){
int t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-')f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
void insert(int x,int y,int id){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
Id[tot]=id;
}
void add(int x,int y,int id){
insert(x,y,id);
insert(y,x,id);
}
void tarjan(int x,int Fa){
dfn[x]=low[x]=++sz;
for (int i=first[x];i;i=next[i])
if (Id[i]!=Fa){
int pur=go[i];
if (!dfn[pur]){
tarjan(pur,Id[i]);
low[x]=std::min(low[x],low[pur]);
if (low[pur]>dfn[x]) pd[Id[i]]=;
}else{
low[x]=std::min(low[x],dfn[pur]);
}
}
}
void bfs(int x){
int h=,t=;c[]=x;vis[x]=;belong[x]=++num;
while (h<=t){
int now=c[h++];
for (int i=first[now];i;i=next[i]){
int pur=go[i];
if (pd[Id[i]]||vis[pur]) continue;
c[++t]=pur;
vis[pur]=;
belong[pur]=num;
}
}
}
bool isroot(int x){
return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;
}
void pushdown(int x){
int l=ch[x][],r=ch[x][];
if (tag[x]!=){
int id=(tag[x]==)?:;
if (l)tag[l]=tag[x];
if (r)tag[r]=tag[x];
if (l&&w[l]) col[l]=id;
if (r&&w[r]) col[r]=id;
if (l) sum[l]=size[l]*id;
if (r) sum[r]=size[r]*id;
tag[x]=;
}
if (rev[x]){
rev[l]^=;
rev[r]^=;
rev[x]=;
std::swap(ch[x][],ch[x][]);
}
}
void updata(int x){
int l=ch[x][],r=ch[x][];
if (w[x]==){
col[x]=;sum[x]=;size[x]=;
if (l) sum[x]+=sum[l],size[x]+=size[l];
if (r) sum[x]+=sum[r],size[x]+=size[r];
return;
}
sum[x]=col[x];size[x]=;
if (l) sum[x]+=sum[l],size[x]+=size[l];
if (r) sum[x]+=sum[r],size[x]+=size[r];
}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
if (ch[y][]==x) l=;else l=;r=l^;
if (!isroot(y)){
if (ch[z][]==y) ch[z][]=x;else ch[z][]=x;
}
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
updata(y);updata(x);
}
void splay(int x){
int top=;st[]=x;
for (int i=x;!isroot(i);i=fa[i])
st[++top]=fa[i];
for (int i=top;i;i--)
pushdown(st[i]);
while (!isroot(x)){
int y=fa[x],z=fa[y];
if (!isroot(y)){
if (ch[y][]==x^ch[z][]==y) rotate(x);
else rotate(y);
}
rotate(x);
}
//updata(x);
}
void access(int x){
for (int t=;x;t=x,x=fa[x]){
splay(x);
ch[x][]=t;
updata(x);
}
}
void makeroot(int x){
access(x);splay(x);rev[x]^=;
}
int find(int x){
access(x);splay(x);
while (ch[x][]) x=ch[x][];
return x;
}
void cut(int x,int y){
makeroot(x);access(y);splay(y);
ch[y][]=fa[ch[y][]]=;
updata(y);
}
void link(int x,int y){
makeroot(x);fa[x]=y;
}
int main(){
n=read();m=read();
for (int i=;i<=m;i++){
e[i].u=read();e[i].v=read();
add(e[i].u,e[i].v,i);
}
for (int i=;i<=n;i++)
if (!dfn[i]) tarjan(i,);
sz=;num=;
for (int i=;i<=n;i++)
if (!vis[i]) bfs(i);
sz=num;
for (int i=;i<=m;i++)
if (belong[e[i].u]!=belong[e[i].v]){
sz++;col[sz]=;tag[sz]=;sum[sz]=;w[sz]=;
size[sz]=;
link(sz,belong[e[i].u]);
link(sz,belong[e[i].v]);
}
int q=read();
while (q--){
int S=read(),T=read(),Num=read(),cnt=;
S=belong[S],T=belong[T];
for (int i=;i<=Num;i++){
e[i].u=read();e[i].v=read();
e[i].u=belong[e[i].u];
e[i].v=belong[e[i].v];
}
for (int i=;i<=Num;i++){
if (e[i].u==e[i].v) continue;
if (find(e[i].u)!=find(e[i].v)){
w[sz+i]=;sum[sz+i]=;
tag[sz+i]=;col[sz+i]=;
size[sz+i]=;
link(e[i].u,sz+i);
link(e[i].v,sz+i);
pd[i]=;
}else{
pd[i]=;
makeroot(e[i].u);access(e[i].v);splay(e[i].v);
tag[e[i].v]=;
}
}
if (find(S)!=find(T)){
puts("-1");
}else{
makeroot(S);access(T);splay(T);
printf("%d\n",sum[T]);
}
for (int i=Num;i>=;i--){
if (e[i].u==e[i].v) continue;
if (pd[i]==){
cut(e[i].u,sz+i);
cut(e[i].v,sz+i);
}else{
makeroot(e[i].u);access(e[i].v);splay(e[i].v);
tag[e[i].v]=-;
}
}
}
}

XJOI网上同步测试DAY14 T3的更多相关文章

  1. XJOI网上同步测试DAY14 T2

    思路:先考虑在D高度的最小圆覆盖,再一层一层往下走时,可以保证圆心与最开始的圆相同的时候答案是最优的. 时间复杂度O(n) 有一个坑点,就是我用了srand(time(NULL))就T了,RP太差了. ...

  2. XJOI网上同步测试DAY14 T1

    思路:线段树维护最短路 #include<cstdio> #include<cmath> #include<iostream> #include<algori ...

  3. XJOI网上同步训练DAY5 T3

    就是对于一个数,我们去考虑把t*****减到(t-1)9999*的代价. #include<cstdio> #include<cmath> #include<algori ...

  4. XJOI网上同步训练DAY1 T3

    思路:一开始看到这题的时候想DP,可是发现貌似不行..因为有前缀也有后缀,而且有的后缀会覆盖到现在的前缀,这就不满足无后效性了啊! 但是有个很巧妙的思路:如果我们知道a[i]的最大值,那么p的数量和q ...

  5. XJOI网上同步训练DAY6 T2

    思路:记得FJ省队集训好像有过这题,可是我太弱了,根本不懂T_T #include<cstdio> #include<iostream> #include<cmath&g ...

  6. XJOI网上同步训练DAY6 T1

    思路:考试的时候直接想出来了,又有点担心复杂度,不过还是打了,居然是直接A掉,开心啊. 我们发现,Ai<=7,这一定是很重要的条件,我们考虑状态压缩,去枚举路径中出现了哪些数字,然后我们把原来n ...

  7. XJOI网上同步训练DAY5 T1

    思路:考虑得出,最终的集合一定是gcd=1的集合,那么我们枚举n个数中哪个数必须选,然后把它质因数分解,由于质数不会超过9个,可以状态压缩,去得出状态为0的dp值就是答案. #include<c ...

  8. XJOI网上同步训练DAY3 T2

    考试的时候已经想出来怎么做了,但是没有时间打了T_T 思路:我们考虑将询问以lim排序,然后树链剖分,把边作为线段树的节点,然后随着询问lim的增大,改变线段树中节点的信息,然后每次询问我们用树链剖分 ...

  9. XJOI网上同步训练DAY3 T1

    思路:看来我真是思博了,这么简单的题目居然没想到,而且我对复杂度的判定也有点问题.. 首先我们选了一个位置i的b,那一定只对i和以后的位置造成改变,因此我们可以这样看: 我们从前往后选,发现一个位置的 ...

随机推荐

  1. thead、tbody、tfoot与顺序无关

    今天发现一个问题,thead.tbody.tfoot等标签的内容排版与顺序无关,做了一个小的实验:

  2. IOS实现小型计算器

    作为一名初学者,编辑一款能够在IOS操作系统上运行的计算器是一件很值得自豪的事情,网络上虽然后很多相关的文章和代码,功能也很强大但是我感觉相关的计算器比加复杂,晦涩难懂,所以我想通过这个小小的计算器, ...

  3. Disposable microfluidic devices: fabrication, function, and application Gina S. Fiorini and Daniel T

    Disposable microfluidic devices: fabrication, function, and application Gina S. Fiorini and Daniel T ...

  4. Android SimpleAdapter ListView (锁定手机,解锁手机的列表)

    SimpleAdapter是扩展性最好的适配器,可以定义各种你想要的布局. 构造方法: SimpleAdapter(Context context, List<? extends Map< ...

  5. linux命令详解--tcpdump

    工作中一直在用tcpdump,感觉非常方便,今天心血来潮百度了一下tcpdump的用法,才发现原来还有这么多强大的功能自己都不知道,那叫一个汗啊. 以此文作为备份,记录一些新知道的用法,各位网友谁有新 ...

  6. Android消息机制(1)

    在Android中,线程内部或者线程之间进行信息交互时经常会使用消息,这些基础的东西如果我们熟悉其内部的原理,将会使我们容易.更好地架构系统,避免一些低级的错误.在学习Android中消息机制之前,我 ...

  7. js 获取元素在页面上的偏移量的最佳方式

    使用js制作效果时,我们常常要获取某个元素在页面上的偏移量(例如tip提示框功能).而获取偏移量可以直接获取相对于document的偏移量,也可以获取相对与视口的偏移量(viewpoint)加上页面滚 ...

  8. apache的500错误是写到哪个文件里面

    apache的500错误是写到哪个文件里面

  9. (转)SVN源码管理(上&下)

    原文地址:http://www.cnblogs.com/IPrograming/archive/2012/12/15/SVN_1.html 使用SVN进行源码管理(上) 在原来的项目中使用的源码管理工 ...

  10. 创建实体数据模型需要注意的,不要选单复数形式,否则AddObject出问题

    //这个测试太不容易了,总是出错,addInfo 方法进去,最后调用context对象.AddObject(),也就是context.AddObject(entitySetName, entity); ...