HDU 5458 Stability 树链剖分

来源:互联网 发布:mysql 联合主键优化 编辑:程序博客网 时间:2024/06/10 22:05

题意:给n个点m条边的无向图,图中可能包含自环和重边,现在有两种操作:
1.删掉一条(a,b)边
2.询问a->b上有多少条关键边,关键边意思为:删掉该边,使得a不能到达b。
所有删除操作都保证图是连通的。

把删除操作倒着加边来搞。
先随便建一颗树,边权为1,若加边(a,b),那么a到b的路径上的边权都赋值为0
询问a b则为a->b的边权和。用树链来搞。

//author: CHC//First Edit Time:    2015-09-21 23:32#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <set>#include <vector>#include <map>#include <queue>#include <set>#include <algorithm>#include <limits>using namespace std;typedef long long LL;const int MAXN=1e+4 * 3 + 1000;const int MAXM=1e+5 * 2 + 1000;const int INF = numeric_limits<int>::max();const LL LL_INF= numeric_limits<LL>::max();struct Edge {    int to,next;    Edge(){}    Edge(int _to,int _next):to(_to),next(_next){}    bool operator<(const Edge &x) const {        if(to!=x.to)return to<x.to;        return next<x.next;    }}e[MAXM];int head[MAXN],tot;int path[MAXN];int Find(int x){    int tx=x;    while(tx!=path[tx])tx=path[tx];    while(x!=path[x]){        int t=path[x];        path[x]=tx;        x=t;    }    return tx;    //return x==path[x]?x:path[x]=Find(path[x]);}bool Union(int x,int y){    x=Find(x),y=Find(y);    if(x==y)return false;    path[x]=y;    return true;}multiset <Edge> S,V;multiset <Edge> ::iterator it,it1;void init(){    memset(head,-1,sizeof(head));    tot=0;    S.clear();V.clear();    for(int i=1;i<MAXN;i++)path[i]=i;}void AddEdge(int u,int v){    e[tot]=Edge(v,head[u]);    head[u]=tot++;    e[tot]=Edge(u,head[v]);    head[v]=tot++;}int dep[MAXN],son[MAXN],siz[MAXN],fa[MAXN],prew[MAXN];int tim,id[MAXN],rid[MAXN],top[MAXN];void dfs1(int u,int father,int w){    fa[u]=father;siz[u]=1;son[u]=-1;    prew[u]=w;    for(int i=head[u];~i;i=e[i].next){        int v=e[i].to;        if(v!=father){            dep[v]=dep[u]+1;            dfs1(v,u,1);            siz[u]+=siz[v];            if(son[u]==-1||siz[v]>siz[son[u]])son[u]=v;        }    }}void dfs2(int u,int tp){    top[u]=tp; id[u]=++tim; rid[tim]=u;    if(son[u]==-1)return ;    dfs2(son[u],tp);    for(int i=head[u];~i;i=e[i].next){        int v=e[i].to;        if(v!=son[u]&&v!=fa[u])dfs2(v,v);    }}#define lson L,mid,rt<<1#define rson mid+1,R,rt<<1|1struct Tree {    int ans,flag;}tr[MAXN<<2];void pushup(int rt){    tr[rt].ans=tr[rt<<1].ans+tr[rt<<1|1].ans;}void pushdown(int rt){    if(tr[rt].flag){        tr[rt<<1].ans=tr[rt<<1|1].ans=0;        tr[rt<<1].flag=tr[rt<<1|1].flag=1;        tr[rt].flag=0;    }}void build(int L,int R,int rt){    tr[rt].flag=0;    if(L==R){        tr[rt].ans=prew[rid[L]];        tr[rt].flag=0;        return ;    }    int mid=(L+R)>>1;    build(lson);build(rson);    pushup(rt);}void update(int L,int R,int rt,int l,int r){    if(tr[rt].ans==0)return ;    if(l<=L&&R<=r){        tr[rt].ans=0;        tr[rt].flag=1;        return ;    }    pushdown(rt);    int mid=(L+R)>>1;    if(l<=mid)update(lson,l,r);    if(r>mid)update(rson,l,r);    pushup(rt);}int query(int L,int R,int rt,int l,int r){    if(tr[rt].ans==0)return 0;    if(l<=L&&R<=r)return tr[rt].ans;    pushdown(rt);    int mid=(L+R)>>1,ans=0;    if(l<=mid)ans+=query(lson,l,r);    if(r>mid)ans+=query(rson,l,r);    pushup(rt);    return ans;}void updatex(int a,int b,int n){    while(top[a]!=top[b]){        if(dep[top[a]]<dep[top[b]])swap(a,b);        update(1,n,1,id[top[a]],id[a]);        a=fa[top[a]];    }    if(a==b)return ;    if(dep[a]>dep[b])swap(a,b);    update(1,n,1,id[son[a]],id[b]);}int queryx(int a,int b,int n){    int ans=0;    while(top[a]!=top[b]){        if(dep[top[a]]<dep[top[b]])swap(a,b);        ans+=query(1,n,1,id[top[a]],id[a]);        a=fa[top[a]];    }    if(a==b)return ans;    if(dep[a]>dep[b])swap(a,b);    ans+=query(1,n,1,id[son[a]],id[b]);    return ans;}struct Q {    int type,a,b;    void init(){        scanf("%d%d%d",&type,&a,&b);    }}cs[MAXN*10];int ans[MAXN*10];int main(){    int T,n,m,q,cas=0;    scanf("%d",&T);    while(T--){        scanf("%d%d%d",&n,&m,&q);        init();        for(int i=0,x,y;i<m;i++){            scanf("%d%d",&x,&y);            if(x>y)swap(x,y);            S.insert(Edge(x,y));        }        //puts("here");        for(int i=0;i<q;i++){            cs[i].init();            if(cs[i].type==1){                if(cs[i].a>cs[i].b)swap(cs[i].a,cs[i].b);                it=S.lower_bound(Edge(cs[i].a,cs[i].b));                S.erase(it);            }        }        //puts("here");        for(it=S.begin();it!=S.end();it++){            if(Union(it->to,it->next)){                V.insert(*it);                AddEdge(it->to,it->next);            }        }        //puts("here3");        for(it=V.begin();it!=V.end();it++){            it1=S.lower_bound(*it);            S.erase(it1);        }        //puts("here");        dep[1]=0;        tim=0;        dfs1(1,1,0);        dfs2(1,1);        build(1,n,1);        for(it=S.begin();it!=S.end();it++){            updatex(it->next,it->to,n);        }        for(int i=q-1;i>=0;i--){            if(cs[i].type==1){                updatex(cs[i].a,cs[i].b,n);            }            else {                ans[i]=queryx(cs[i].a,cs[i].b,n);            }        }        printf("Case #%d:\n",++cas);        for(int i=0;i<q;i++)            if(cs[i].type==2)printf("%d\n",ans[i]);    }    return 0;}
0 0