zoukankan      html  css  js  c++  java
  • hdu 6200 mustedge mustedge mustedge(dfs序+树状数组+并查集)

    题目链接:hdu 6200 mustedge mustedge mustedge

    题意:

    一开始给你一个有n个节点m条无向边的图,现在定义mustedge为u->v的路径上必须经过的边。

    现在有q个操作:

    1 x y x->y加条无向边

    2 x y 查询x->y上有多少条mustedge。

    题解:

    贴一下叉姐的题解:

    固定一颗生成树,加非树边 (u, v)相当于把 uu到 v 路径上的边涂黑,询问相当于询问路径上白边的数量。

    用一个并查集 j(u) 维护点 u 向上第一条白边的位置,每次修改的时候暴力沿着 j(*) 找。
    之后用树状数组维护 u 到路径上白边的数量,涂黑一条白边相当于子树整体减 1。

    由于只有n个点,所以暴力合并的时候最多只会合并n次。

    然后维护路径可以用树链剖分+线段树,但是这个是双log的,比较慢。

    叉姐这样的维护方式只有1个log。

    所以总体复杂度就是nlogn。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=(a);i<=(b);++i)
     3 using namespace std;
     4 typedef pair<int,int>P;
     5 #define mst(a,b) memset(a,b,sizeof(a))
     6 
     7 const int N=1e5+7;
     8 int t,n,m,q,sum[N],cas,f[N];
     9 int nxt[2*N],g[N],v[2*N],ed,x,y,op;
    10 int hs[N],fa[N],top[N],dep[N],sz[N],dfsl[N],dfsr[N],idx; 
    11 vector<P>edge;
    12 
    13 void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}  
    14 
    15 void dfs1(int u,int pre){
    16     dfsl[u]=++idx,dep[u]=dep[pre]+1,hs[u]=0,fa[u]=pre,sz[u]=1;
    17     for(int i=g[u];i;i=nxt[i])if(v[i]!=pre)
    18     dfs1(v[i],u),sz[u]+=sz[v[i]],hs[u]=(sz[v[i]]>sz[hs[u]])?v[i]:hs[u];
    19     dfsr[u]=idx;
    20 }
    21 void dfs2(int u,int tp){
    22     top[u]=tp;
    23     if(hs[u])dfs2(hs[u],tp);
    24     for(int i=g[u];i;i=nxt[i])
    25     if(v[i]!=fa[u]&&v[i]!=hs[u])dfs2(v[i],v[i]);
    26 }
    27 
    28 int LCA(int x,int y)
    29 {
    30     while(top[x]!=top[y])
    31         dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
    32     return dep[x]<dep[y]?x:y;
    33 }
    34 
    35 inline void add(int x,int c){while(x<=n)sum[x]+=c,x+=x&-x;}
    36 inline int ask(int x){int an=0;while(x)an+=sum[x],x-=x&-x;return an;}
    37 
    38 inline int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
    39 void merge(int x,int y){f[find(x)]=find(y);}
    40 
    41 void addedge(int x,int y)
    42 {
    43     int fx=find(x),fy=find(y);
    44     if(fx==fy)return;
    45     int lca=find(LCA(x,y));
    46     while(find(x)!=find(lca))
    47     {
    48         add(dfsl[fx=find(x)],1);
    49         add(dfsr[fx]+1,-1);
    50         merge(fx,fa[fx]);
    51     }
    52     while(find(y)!=find(lca))
    53     {
    54         add(dfsl[fy=find(y)],1);
    55         add(dfsr[fy]+1,-1);
    56         merge(fy,fa[fy]);
    57     }
    58 }
    59 
    60 int main(){
    61     scanf("%d",&t);
    62     while(t--)
    63     {
    64         printf("Case #%d:
    ",++cas);
    65         scanf("%d%d",&n,&m);
    66         edge.clear(),mst(g,0),ed=0;
    67         F(i,1,n)f[i]=i,sum[i]=0;
    68         F(i,1,m)
    69         {
    70             scanf("%d%d",&x,&y);
    71             if(find(x)!=find(y))adg(x,y),adg(y,x),merge(x,y);
    72             else edge.push_back(P(x,y));
    73         }
    74         idx=0,dfs1(1,0),dfs2(1,1);
    75         F(i,1,n)f[i]=i;
    76         for(auto &it:edge)addedge(it.first,it.second);
    77         scanf("%d",&q);
    78         while(q--)
    79         {
    80             scanf("%d%d%d",&op,&x,&y);
    81             if(op==1)addedge(x,y);
    82             else 
    83             {
    84                 int lca=LCA(x,y);
    85                 printf("%d
    ",dep[x]+dep[y]-2*dep[lca]-(ask(dfsl[x])+ask(dfsl[y])-2*ask(dfsl[lca])));
    86             }
    87         }
    88     }
    89     return 0;
    90 }
    View Code
  • 相关阅读:
    eclipse的安装
    第一章:Javascript语言核心
    jQuery理解之(二)功能函数
    jQuery理解之(一)动画与特效
    jQuery实现单击和鼠标感应事件。
    jQuery使用之(五)处理页面的事件
    jQuery使用之(四)处理页面的表单元素
    jQuery使用之(三)处理页面的元素
    jQuery使用之(二)设置元素的样式
    jQuery使用之(一)标记元素属性
  • 原文地址:https://www.cnblogs.com/bin-gege/p/7683558.html
Copyright © 2011-2022 走看看