3910: 火车
2017-03-05 19:48
148 查看
题目链接
题目大意:n点m边,从a出发,一次经过k个点,已去过的不用去,剩下的必须依次去,求经过多少边
题解:用并查集将一段合成一个点,每个点最多只能被合一次,保证时间复杂度。查询的时候像链剖一样一段一段往上跳就行了,还要顺便把路径上的所有点缩起来。
题目大意:n点m边,从a出发,一次经过k个点,已去过的不用去,剩下的必须依次去,求经过多少边
题解:用并查集将一段合成一个点,每个点最多只能被合一次,保证时间复杂度。查询的时候像链剖一样一段一段往上跳就行了,还要顺便把路径上的所有点缩起来。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int M=500005; #define L 18 int t,n,q,now; long long ans;//long long!! int dep[M],fa[M][22];//倍增 int f[M],head[M];//并查集 struct edge{int to,nex;}e[M*2]; void add(int u,int v){e[t].to=v,e[t].nex=head[u],head[u]=t++;} int fid(int x){return f[x]==x?x:f[x]=fid(f[x]);} int lca(int x,int y){ if(dep[x]<dep[y]) swap(x,y); for(int i=L;i>=0;i--) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i]; if(x==y) return x; for(int i=L;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } void dfs(int x){ for(int i=head[x];i!=-1;i=e[i].nex){ int v=e[i].to; if(v!=fa[x][0]){ fa[v][0]=x,dep[v]=dep[x]+1; dfs(v); } } } void ST() { for(int j=1;j<=L;j++) for(int i=1;i<=n;i++) fa[i][j]=fa[fa[i][j-1]][j-1]; } void oper(int x,int y,int c){ x=f[x],y=f[y]; while(dep[x]>=dep[c]) f[x]=f[fa[x][0]],x=f[x];//跳跃向上 while(dep[y]>=dep[c]) f[y]=f[fa[y][0]],y=f[y]; } void work() { int x,c; while(q--) { scanf("%d",&x); if(fid(x)!=x) continue; c=lca(x,now); ans+=dep[x]+dep[now]-2*dep[c]; oper(now,x,c);now=x; } cout<<ans<<endl; } void init() { int x,y;t=0; memset(head,-1,sizeof(head)); cin>>n>>q>>now; for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); add(x,y),add(y,x); } for(int i=1;i<=n;i++) f[i]=i; dep[1]=1;dfs(1);ST(); } int main() { init(); work(); return 0; }
相关文章推荐
- 【bzoj3910】火车 LCA+并查集
- BZOJ 3910 火车 LCA+并查集
- BZOJ 3910: 火车|LCA|并查集
- 3910: 火车 LCA+并查集
- 【BZOJ3910】火车 LCA+并查集
- 【BZOJ-3910】火车 倍增LCA + 并查集
- BZOJ 3910: 火车
- bzoj3910: 火车
- 【BZOJ 3910】火车 并查集
- bzoj 3910: 火车
- [bzoj3910] 火车
- [bzoj3910]火车_并查集_倍增LCA
- BZOJ3910 火车
- [BZOJ3910]火车(lca+树链剖分)
- 【bzoj3910】【火车】【lca+并查集】
- niu已经在火车上了
- 《明朝皇帝坐火车》
- 借火车看设计过程
- 解决dede生成静态页和动态页转换的一些问题,及火车采集入库生成动态的办法
- 极品时刻表2007.9.2(方便大家查火车时间)