BZOJ1969: [Ahoi2005]LANE 航线规划
题解 :LCT动态缩环即可
/**************************************************************
Problem: 1969
User: c20161007
Language: C++
Result: Accepted
Time:856 ms
Memory:6692 kb
****************************************************************/
#include <bits/stdc++.h>
#define ll long long
const int MAXN=3e4+10;
const int NM=1e5+10;
using namespace std;
int rt[MAXN],size[MAXN],minn[MAXN],ch[MAXN][2],res[MAXN],pre[MAXN];
int key[MAXN],fa[MAXN];
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}
void newnode(int pos){
rt[pos]=1;size[pos]=1;minn[pos]=key[pos]=pos;ch[pos][0]=ch[pos][1]=0;res[pos]=0;pre[pos]=0;fa[pos]=pos;
}
int find1(int x){
if(x==fa[x])return x;
else return fa[x]=find1(fa[x]);
}
void reverse(int r){
if(!r)return ;
swap(ch[r][0],ch[r][1]);
res[r]^=1;
}
void push(int x){
if(res[x]){
reverse(ch[x][0]);
reverse(ch[x][1]);
res[x]=0;
}
}
void up(int x){
minn[x]=min(minn[ch[x][0]],minn[ch[x][1]]);
minn[x]=min(minn[x],key[x]);
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void P(int x){
if(!rt[x])P(find1(pre[x]));
push(x);
}
void rotate(int x,int kind){
int y=find1(pre[x]);
ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y;
if(rt[y])rt[x]=1,rt[y]=0;
else ch[find1(pre[y])][ch[find1(pre[y])][1]==y]=x;
pre[x]=find1(pre[y]);ch[x][kind]=y;pre[y]=x;up(y);
}
void splay(int x){
P(x);
while(!rt[x]){
if(rt[find1(pre[x])])rotate(x,ch[find1(pre[x])][0]==x);
else{
int y=find1(pre[x]);int kind=ch[find1(pre[y])][0]==y;
if(ch[y][kind]==x)rotate(x,!kind),rotate(x,kind);
else rotate(y,kind),rotate(x,kind);
}
}
up(x);
}
void access(int x){
int y=0;//cout<<x<<"-----===="<<endl;
while(x){
splay(x);
if(ch[x][1])pre[ch[x][1]]=x,rt[ch[x][1]]=1,ch[x][1]=0;
if(rt[y])rt[y]=0;
ch[x][1]=y;up(x);
y=x;x=find1(pre[x]);
}
}
void mroot(int x){
access(x);splay(x);reverse(x);
}
bool pd(int u,int v){
while(pre[u])u=find1(pre[u]);
while(pre[v])v=find1(pre[v]);
return u==v;
}
void Link(int u,int v){
mroot(u);mroot(v);pre[u]=v;
}
vector<int>vec;
void dfs(int v){
if(!v)return ;
vec.push_back(v);
dfs(ch[v][0]);
dfs(ch[v][1]);
}
void destory(int u,int v){
mroot(u);access(v);splay(v);
// cout<<u<<" "<<v<<endl;
// cout<<"sb"<<endl;
int tx=minn[v];
// cout<<tx<<endl;
dfs(v);
// cout<<tx<<endl;
for(int i=0;i<vec.size();i++)fa[vec[i]]=tx,ch[vec[i]][0]=ch[vec[i]][1]=0,rt[vec[i]]=1;
// cout<<endl;
//cout<<tx<<endl;
for(int i=0;i<vec.size();i++)pre[vec[i]]=0;
vec.clear();
up(tx);
}
void slove(int u,int v){
u=find1(u);v=find1(v);
// cout<<pd(u,v)<<endl;
if(pd(u,v)) destory(u,v);
else Link(u,v);
}
int querty(int u,int v){
u=find1(u);v=find1(v);
//cout<<u<<" "<<v<<endl;
mroot(u);access(v);
// cout<<"sb"<<endl;
splay(v);
return size[v]-1;
}
typedef struct node{
int op,u,v;
}node;
node que[NM];
set<pair<int,int> >s;
set<pair<int,int> >::iterator ite;
stack<int>ss;
int main(){
minn[0]=1e9+7;
int n,m;n=read();m=read();
for(int i=1;i<=n;i++)newnode(i);
int u,v,op;
for(int i=1;i<=m;i++){u=read(),v=read();
if(u>v)swap(u,v);
s.insert(make_pair(u,v));}
int cnt=0;
while(scanf("%d",&op)!=EOF){
if(op==-1)break;
que[++cnt].op=op;que[cnt].u=read();que[cnt].v=read();
if(que[cnt].op==1)continue;
// cout<<cnt<<endl;
// cout<<que[cnt].op<<" "<<que[cnt].u<<" "<<que[cnt].v<<endl;
if(que[cnt].u>que[cnt].v)swap(que[cnt].u,que[cnt].v);
s.erase(s.find(make_pair(que[cnt].u,que[cnt].v)));
}
// cout<<cnt<<endl;
for(ite=s.begin();ite!=s.end();ite++){
slove(ite->first,ite->second);
}
// cout<<"sb"<<endl;
// cout<<minn[1]<<endl;
for(int i=cnt;i>=1;i--){
if(que[i].op==1){
ss.push(querty(que[i].u,que[i].v));
// cout<<"sb"<<endl;
}
else slove(que[i].u,que[i].v);
}
// cout<<"sb"<<endl;
while(!ss.empty()){
printf("%d\n",ss.top());
ss.pop();
}
return 0;
}
1969: [Ahoi2005]LANE 航线规划
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 637 Solved: 287
[Submit][Status][Discuss]
Description
对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系。
星际空间站的Samuel II巨型计算机经过长期探测,已经锁定了Samuel星系中许多星球的空间坐标,并对这些星球从1开始编号1、2、3……。
一些先遣飞船已经出发,在星球之间开辟探险航线。
探险航线是双向的,例如从1号星球到3号星球开辟探险航线,那么从3号星球到1号星球也可以使用这条航线。
例如下图所示:
在5个星球之间,有5条探险航线。
A、B两星球之间,如果某条航线不存在,就无法从A星球抵达B星球,我们则称这条航线为关键航线。
显然上图中,1号与5号星球之间的关键航线有1条:即为4-5航线。
然而,在宇宙中一些未知的磁暴和行星的冲撞,使得已有的某些航线被破坏,随着越来越多的航线被破坏,探险飞船又不能及时回复这些航线,可见两个星球之间的关键航线会越来越多。
假设在上图中,航线4-2(从4号星球到2号星球)被破坏。此时,1号与5号星球之间的关键航线就有3条:1-3,3-4,4-5。
小联的任务是,不断关注航线被破坏的情况,并随时给出两个星球之间的关键航线数目。现在请你帮助完成。
在5个星球之间,有5条探险航线。
A、B两星球之间,如果某条航线不存在,就无法从A星球抵达B星球,我们则称这条航线为关键航线。
显然上图中,1号与5号星球之间的关键航线有1条:即为4-5航线。
然而,在宇宙中一些未知的磁暴和行星的冲撞,使得已有的某些航线被破坏,随着越来越多的航线被破坏,探险飞船又不能及时回复这些航线,可见两个星球之间的关键航线会越来越多。
假设在上图中,航线4-2(从4号星球到2号星球)被破坏。此时,1号与5号星球之间的关键航线就有3条:1-3,3-4,4-5。
小联的任务是,不断关注航线被破坏的情况,并随时给出两个星球之间的关键航线数目。现在请你帮助完成。
Input
第一行有两个整数N,M。表示有N个星球(1< N
< 30000),初始时已经有M条航线(1 < M <
100000)。随后有M行,每行有两个不相同的整数A、B表示在星球A与B之间存在一条航线。接下来每行有三个整数C、A、B。C为1表示询问当前星球A和星球B之间有多少条关键航线;C为0表示在星球A和星球B之间的航线被破坏,当后面再遇到C为1的情况时,表示询问航线被破坏后,关键路径的情况,且航线破坏后不可恢复;
C为-1表示输入文件结束,这时该行没有A,B的值。被破坏的航线数目与询问的次数总和不超过40000。
Output
对每个C为1的询问,输出一行一个整数表示关键航线数目。
注意:我们保证无论航线如何被破坏,任意时刻任意两个星球都能够相互到达。在整个数据中,任意两个星球之间最多只可能存在一条直接的航线。
Sample Input
5 5
1 2
1 3
3 4
4 5
4 2
1 1 5
0 4 2
1 5 1
-1
1 2
1 3
3 4
4 5
4 2
1 1 5
0 4 2
1 5 1
-1
Sample Output
1
3

浙公网安备 33010602011771号