[AHOI2005] route planning

The meaning of problems

FIG n points to a m edges, there are two operations: interrogation path must pass through x to y has several sides, remove x, y connected directly between the edges.

1 <N <30000,1 <M <100000, the total number of operations is not more than 40,000

We guarantee that no matter how the route is destroyed, any time any two planets are able to reach each other. Throughout the data, any possible only up to a direct route between the two planets.

answer

A necessary side is the bridge (deleting the x, y do not communicate that), but bad maintenance. Because whenever two o'clock connectivity, so consider a special case: a tree, a tree by the side edges are necessary, consider the plus side will have any effect, will cause the tree to x y path is not a necessary side, of course, add to the mix of edge no. So it is well maintained, and considered back in time, to build a tree by the side did not destroy, modify the plus side is the path, the query is a query path, cross a tree on it. Those non-tree edges do not destroy it follow the path modify add to the mix on it.

Looking to destroy that which edge a bit sick (there may I write the wrong way), it is useful to see the hash.

Because there is a path, assign a value to the son node, then query and modify Finally, it should be id [x] +1

 

#include<bits/stdc++.h>
using namespace std;

const int maxn=40005;
const int maxm=100005;
int n,m,cnt,num;
int fa[maxn];
bool broken[maxm];//broken 1:没用到的没炸的边
int dep[maxn],size[maxn],son[maxn],id[maxn],top[maxn];
int root,ls[maxn<<1],rs[maxn<<1],sum[maxn<<1];
int tot,ans[maxn];
vector<int>cx[maxn];
struct edge{
  int x,y;
}e[maxm];
struct question{
  int op,x,y,id;
}q[maxn];

template<class T>inline void read(T &x){
  x=0;int f=0;char ch=getchar();
  while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();}
  while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  x= f ? -x : x ;
}

bool cmp(edge a,edge b){
  if(a.x==b.x) return a.y<b.y;
  return a.x<b.x;
}

bool cmp1(question a,question b){
  if(a.op!=b.op) return a.op<b.op;
  if(a.x==b.x) return a.y<b.y;
  return a.x<b.x;
}

bool cmp2(question a,question b){
  return a.id>b.id;
}

int find(int x){
  return fa[x]==x ? x : fa[x]=find(fa[x]);
}

void connect(int x,int y,int i){
  int dx=find(x),dy=find(y);
  if(dx!=dy){
    cx[x].push_back(y);
    cx[y].push_back(x);
    fa[dx]=dy;
  }
  else broken[i]=true;
}

void dfs(int u){
  size[u]=1;
  for(unsigned int i=0;i<cx[u].size();i++){
    int v=cx[u][i];
    if(v==fa[u]) continue;
    fa[v]=u;
    dep[v]=dep[u]+1;
    dfs(v);
    size[u]+=size[v];
    if(size[son[u]]<size[v]) son[u]=v;
  }
}

void dfs(int u,int tp){
  id[u]=++num;
  top[u]=tp;
  if(!son[u]) return ;
  dfs(son[u],tp);
  for(unsigned int i=0;i<cx[u].size();i++){
    int v=cx[u][i];
    if(v==fa[u]||v==son[u]) continue;
    dfs(v,v);
  }
}

void update(int rt){
  sum[rt]=sum[ls[rt]]+sum[rs[rt]];
}

void build(int &rt,int l,int r){
  rt=++num;
  if(l==r){
    sum[rt]=1;
    return ;
  }
  int mid=(l+r)>>1;
  build(ls[rt],l,mid);
  build(rs[rt],mid+1,r);
  update(rt);
}

void modify(int rt,int l,int r,int a_l,int a_r){
  if(!sum[rt]) return ;
  if(a_l<=l&&r<=a_r){
    sum[rt]=0;
    return ;
  }
  int mid=(l+r)>>1;
  if(a_l<=mid) modify(ls[rt],l,mid,a_l,a_r);
  if(mid<a_r) modify(rs[rt],mid+1,r,a_l,a_r);
  update(rt);
}

void modify(int x,int y){
  while(top[x]!=top[y]){
    if(dep[top[x]]>dep[top[y]]) swap(x,y);
    modify(1,1,n,id[top[y]],id[y]);
    y=fa[top[y]];
  }
  if(dep[x]>dep[y]) swap(x,y);
  modify(1,1,n,id[x]+1,id[y]);
}

int query(int rt,int l,int r,int a_l,int a_r){
  if(!sum[rt]) return sum[rt];
  if(a_l<=l&&r<=a_r) return sum[rt];
  int mid=(l+r)>>1;
  int ret=0;
  if(a_l<=mid) ret+=query(ls[rt],l,mid,a_l,a_r);
  if(mid<a_r) ret+=query(rs[rt],mid+1,r,a_l,a_r);
  return ret;
}

int query(int x,int y){
  int ret=0;
  while(top[x]!=top[y]){
    if(dep[top[x]]>dep[top[y]]) swap(x,y);
    ret+=query(1,1,n,id[top[y]],id[y]);
    y=fa[top[y]];
  }
  if(dep[x]>dep[y]) swap(x,y);
  ret+=query(1,1,n,id[x]+1,id[y]);
  return ret;
}

int main(){
  read(n);read(m);
  for(int i=1;i<=n;i++) fa[i]=i;
  for(int i=1;i<=m;i++){
    read(e[i].x);read(e[i].y);
    if(e[i].x>e[i].y) swap(e[i].x,e[i].y);
  }
  while(1){
    read(q[++cnt].op);
    if(q[cnt].op==-1) {cnt--;break;}
    read(q[cnt].x);
    read(q[cnt].y);
    q[cnt].id=cnt;
    if(q[cnt].x>q[cnt].y) swap(q[cnt].x,q[cnt].y);
  }
  sort(e+1,e+m+1,cmp);
  sort(q+1,q+cnt+1,cmp1);
  for(int i=1,j=1;;j++){
    while(j<=cnt&&!q[j].op&&i<=m&&(q[j].x!=e[i].x||q[j].y!=e[i].y))
      connect(e[i].x,e[i].y,i),i++;
    if(i>m) break;
    if(j>cnt||q[j].op) connect(e[i].x,e[i].y,i);
    i++;
  }
  memset(fa,0,sizeof(fa));
  dep[1]=1;
  dfs(1);
  dfs(1,1);
  num=0;
  build(root,1,n);
  for(int i=1;i<=m;i++)
   if(broken[i]) modify(e[i].x,e[i].y);
  sort(q+1,q+cnt+1,cmp2);
  for(int i=1;i<=cnt;i++){
    if(!q[i].op) modify(q[i].x,q[i].y);
    else ans[++tot]=query(q[i].x,q[i].y);
  }
  for(int i=tot;i;i--) printf("%d\n",ans[i]);
}
View Code

 

Guess you like

Origin www.cnblogs.com/sto324/p/11345140.html