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:\n",++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\n",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

 

posted @ 2017-10-17 19:52  bin_gege  阅读(235)  评论(0编辑  收藏  举报