poj1986Distance Queries(RMQ+LCA)
题目连接:http://poj.org/problem?id=1986
感觉比离线的难理解一些。。
参考:http://www.cnblogs.com/scau20110726/archive/2013/05/26/3100812.html
http://www.cnblogs.com/BruceNoOne/archive/2013/07/26/3217486.html
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=40008; 7 int dis[maxn],vis[maxn]; 8 int first[maxn*2],node[maxn*2],dep[maxn*2],dp[maxn*2][25]; 9 struct edge 10 { 11 int v,w,nex; 12 }e[maxn*2]; 13 14 int head[maxn]; 15 int cnt; 16 17 void add(int u,int v,int w) 18 { 19 e[cnt].v=v; 20 e[cnt].w=w; 21 e[cnt].nex=head[u]; 22 head[u]=cnt++; 23 } 24 25 void dfs(int &id,int u,int d,int w) 26 { 27 id++; 28 node[id]=u; //树变数组,第一次经过该点 29 dep[id]=d; //深度 30 vis[u]=1; 31 first[u]=id; //第一次出现 32 for(int i=head[u];i!=-1;i=e[i].nex) if(!vis[e[i].v]) //遍历 33 { 34 dis[e[i].v]=w+e[i].w; 35 dfs(id,e[i].v,d+1,dis[e[i].v]); //往下一路到底 36 id++; 37 node[id]=u; //第二次经过该点 38 dep[id]=d; //记录深度 39 } 40 } 41 void RMQ_init(int n) 42 { 43 int k = log2(n); // 要选用g++,才能用log2 44 for(int i=1;i<=n;i++) dp[i][0]=i; //记录最小值的下标,初始化 45 for(int j=1;j<=k;j++) 46 for(int i=1;i+(1<<j)-1<=n;i++) 47 { 48 int a=dp[i][j-1]; 49 int b=dp[i+(1<<j-1)][j-1]; //一定要注意位运算优先级 50 if(dep[a]<dep[b]) dp[i][j]=a; 51 else dp[i][j]=b; 52 } 53 } 54 55 int rmq(int x,int y) 56 { 57 int k=log2(y-x+1); 58 int a=dp[x][k]; 59 int b=dp[y-(1<<k)+1][k]; 60 if(dep[a]<dep[b]) return a; 61 else return b; 62 } 63 64 int lca(int a,int b) //返回最近公共祖先 65 { 66 int x=first[a]; 67 int y=first[b]; 68 int k; 69 if(x<=y) 70 { 71 k=rmq(x,y); 72 return node[k]; 73 } 74 else 75 { 76 k=rmq(y,x); 77 return node[k]; 78 } 79 } 80 int main() 81 { 82 int n,m; 83 while(scanf("%d%d",&n,&m)!=EOF) 84 { 85 cnt=0; 86 memset(head,-1,sizeof(head)); 87 int u,v,w; 88 char s[10]; 89 while(m--) 90 { 91 scanf("%d%d%d%s",&u,&v,&w,s); 92 add(u,v,w); 93 add(v,u,w); 94 } 95 int tot=0; 96 memset(vis,0,sizeof(vis)); 97 memset(dis,0,sizeof(dis)); 98 dfs(tot,1,1,0); 99 RMQ_init(tot); 100 int k; 101 scanf("%d",&k); 102 while(k--) 103 { 104 scanf("%d%d",&u,&v); 105 printf("%d\n",dis[u]+dis[v]-2*dis[lca(u,v)]); 106 107 } 108 } 109 return 0; 110 111 }