标签:
题目链接:
Time Limit: 2000MS | Memory Limit: 30000K | |
Total Submissions: 11531 | Accepted: 4068 | |
Case Time Limit: 1000MS |
Description
Input
Output
Sample Input
7 6 1 6 13 E 6 3 9 E 3 5 7 S 4 1 3 N 2 4 20 W 4 7 2 S 3 1 6 1 4 2 6
Sample Output
13 3 36
题意:
给一棵树;问两点之间的距离;
思路:
lca的模板题,一开始莫名其妙的wa了,看了好久才发现是一个地方写反了;后来又tle,把cin改成scanf就好了;看来还是不能用cin;
AC代码:
/*2014300227 1986 Accepted 13984K 485MS G++ 2077B*/ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int N=4e4+4; typedef long long ll; const double PI=acos(-1.0); int n,m,cnt,head[N],vis[N],a[2*N],dep[N],first[N],dis[N],num,dp[2*N][30],p[N]; struct Edge { int to,next,val; }; Edge edge[2*N]; void add_edge(int s,int e,int va) { edge[cnt].to=e; edge[cnt].next=head[s]; edge[cnt].val=va; head[s]=cnt++; } int dfs(int x,int deep) { vis[x]=1; first[x]=num; a[num++]=x; dep[x]=deep; for(int i=head[x];i!=-1;i=edge[i].next) { int y=edge[i].to; if(!vis[y]) { dis[y]=dis[x]+edge[i].val; dfs(y,deep+1); a[num++]=x; } } } int RMQ() { for(int i=0;i<num;i++) { dp[i][0]=a[i]; } for(int j=1;(1<<j)<=num;j++) { for(int i=0;i+(1<<j)-1<num;i++) { if(dep[dp[i][j-1]]<dep[dp[i+(1<<(j-1))][j-1]])dp[i][j]=dp[i][j-1]; else dp[i][j]=dp[i+(1<<(j-1))][j-1]; } } } int query(int l,int r) { int temp=(int)(log((r-l+1)*1.0)/log(2.0)); if(dep[dp[l][temp]]<dep[dp[r-(1<<temp)+1][temp]])return dp[l][temp]; else return dp[r-(1<<temp)+1][temp]; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { cnt=0; num=0; for(int i=0;i<=n;i++) { vis[i]=0; head[i]=-1; } int u,v,w; char s[10]; for(int i=0;i<m;i++) { scanf("%d%d%d%s",&u,&v,&w,s); //cin>>u>>v>>w>>s; add_edge(u,v,w); add_edge(v,u,w); } dis[1]=0; dfs(1,0); RMQ(); int q,fx,fy; scanf("%d",&q); while(q--) { scanf("%d%d",&fx,&fy); int lca; if(first[fx]<first[fy]) { lca=query(first[fx],first[fy]); } else lca=query(first[fy],first[fx]); printf("%d\n",dis[fx]+dis[fy]-2*dis[lca]); } } return 0; }
poj-1986 Distance Queries(lca+ST+dfs)
标签:
原文地址:http://www.cnblogs.com/zhangchengc919/p/5379596.html