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;}
相关文章推荐
- 多线程TcpServer
- HttpHandler与HttpModule的用处与区别
- hibernate生成表中有BLOB字段的javabean,hql查询出现无效列类型异常
- 浏览器缓存处理方法、系统及代理服务器
- php如何在某个时间上加一天?一小时?一星期?一个月?
- 《编程之法》1.4字符串转换成整数
- 【数据结构】数组
- scale相关设置—手动设置
- c语言中的位操作
- visio 2010 激活方法
- Html初学之路01
- windows系统使用Tera Term连接虚拟机(VMware Workstation) 中的Linux(CentOS)
- Java NIO VS IO
- 自定义方法,模仿each遍历多维数组
- java模拟getpost请求
- PHP中获取当前页面的完整URL
- 如何在sublime内调试Javascript代码
- mysql 如何判断 "字符串" 是否为 "数字"
- php常见设计模式
- JavaScript、HTML、CSS、JSP的注释方法