您的位置:首页 > 其它

HDU2586 How far away ?(LCA在线RMQ-ST)

2016-07-16 13:39 477 查看
题目点我点我点我题目大意:求两个节点间最短距离。解题思路:LCA(最近公共祖先),dis[i]表示从根节点到节点i的距离,所以要求节点u和节点v之间的距离则有dis[u]+dis[v]-2*dis[LCA(u,v)]。此处我是基于RMQ-ST写的。第一次写这种题,过了样例却wa了一整页,度娘来的基本都是Tarjan算法的,没有多少是用RMQ写的,极其心累,调了一上午bug,才发现要先dfs再ST……ORZ。另在讨论区发现一组挺好的数据:
1
5 3
1 2 100
1 3 200
2 4 300
2 5 100
4 5
3 4
2 3

结果
400
600
300
/* ***********************************************┆  ┏┓   ┏┓ ┆┆┏┛┻━━━┛┻┓ ┆┆┃       ┃ ┆┆┃   ━   ┃ ┆┆┃ ┳┛ ┗┳ ┃ ┆┆┃       ┃ ┆┆┃   ┻   ┃ ┆┆┗━┓ 马 ┏━┛ ┆┆  ┃ 勒 ┃  ┆      ┆  ┃ 戈 ┗━━━┓ ┆┆  ┃ 壁     ┣┓┆┆  ┃ 的草泥马  ┏┛┆┆  ┗┓┓┏━┳┓┏┛ ┆┆   ┃┫┫ ┃┫┫ ┆┆   ┗┻┛ ┗┻┛ ┆************************************************ */#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>using namespace std;#define rep(i,a,b) for (int i=(a),_ed=(b);i<=_ed;i++)#define per(i,a,b) for (int i=(b),_ed=(a);i>=_ed;i--)#define pb push_back#define mp make_pairconst int inf_int = 2e9;const long long inf_ll = 2e18;#define inf_add 0x3f3f3f3f#define mod 1000000007#define LL long long#define ULL unsigned long long#define MS0(X) memset((X), 0, sizeof((X)))#define SelfType intSelfType Gcd(SelfType p,SelfType q){return q==0?p:Gcd(q,p%q);}SelfType Pow(SelfType p,SelfType q){SelfType ans=1;while(q){if(q&1)ans=ans*p;p=p*p;q>>=1;}return ans;}#define Sd(X) int (X); scanf("%d", &X)#define Sdd(X, Y) int X, Y; scanf("%d%d", &X, &Y)#define Sddd(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}//#pragma comment(linker, "/STACK:102400000,102400000")const int N = 40010;int dp[2*N][20],dis;struct edge{int to,next,w;}e[2*N];int last,cnt;void addedge(int u,int v,int w){e[++cnt] = edge{v,last[u],w};last[u] = cnt;e[++cnt] = edge{u,last[v],w};last[v] = cnt;}int vs[2*N];   //DFS访问的顺序int dep[2*N];  //节点的深度int ver;    //各个顶点在vs中首次出现的下标void dfs(int v,int p,int d,int &k){ver[v] = k;vs[k] = v;dep[k++] = d;for(int i=last[v];i!=-1;i=e[i].next){if(e[i].to!=p){dis[e[i].to]=dis[v]+e[i].w;dfs(e[i].to,v,d+1,k);vs[k] = v;dep[k++] = d;}}}void st(int n){for(int i=0;i<=n;i++)dp[i][0]=i;for(int j=1;(1<<j)<=n;j++){for(int i=1;i+(1<<j)-1<n;i++){int a = dp[i][j-1] , b = dp[i+(1<<(j-1))][j-1];dp[i][j] = dep[a]<dep[b]?a:b;}}}int rmq(int l,int r){int k = (int)(log(1.0*(r-l+1))/log(2.0));int a = dp[l][k];int b = dp[r-(1<<k)+1][k];return dep[a]<dep[b]?a:b;}int LCA(int u,int v){int x = ver[u], y = ver[v];if(x>y)swap(x,y);int res = rmq(x,y);return vs[res];}int main(){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);ios::sync_with_stdio(0);cin.tie(0);Sd(cas);while(cas--){Sdd(n,q);cnt = 0;memset(last,-1,sizeof last);for(int i=1;i<n;i++){Sddd(u,v,w);addedge(u,v,w);}for(int i=0;i<=n;i++) dis[i] = -1;dis[1] = 0;int k = 0;dfs(1,-1,0,k);st(2*n-1);while(q--){Sdd(l,r);printf("%d\n",dis[l]+dis[r]-2*dis[LCA(l,r)]);}}return 0;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: