poj 1986 Distance Queries(LCA:倍增/离线)
计算树上的路径长度。input要去查poj 1984。
任意建一棵树,利用树形结构,将问题转化为u,v,lca(u,v)三个点到根的距离。输出d[u]+d[v]-2*d[lca(u,v)]。
倍增求解:
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 #define rep(i,a,b) for(int i=a;i<=b;i++) 6 #define clr(a,m) memset(a,m,sizeof(a)) 7 using namespace std; 8 9 const int MAXN=44444; 10 const int POW = 18; 11 12 struct Edge{ 13 int v,next,c; 14 Edge(){} 15 Edge(int _v,int _c,int _next):v(_v),c(_c),next(_next){} 16 }edge[MAXN<<1]; 17 18 int head[MAXN],tol; 19 int p[MAXN][POW],d[MAXN]; 20 int vis[MAXN],dis[MAXN]; 21 queue<int>q; 22 23 void init() 24 { 25 tol=0; 26 clr(head,-1); 27 } 28 29 void add(int u,int v,int c) 30 { 31 edge[tol]=Edge(v,c,head[u]); 32 head[u]=tol++; 33 } 34 35 void bfs(int x) 36 { 37 clr(vis,0); 38 clr(dis,0); 39 while(!q.empty()) 40 q.pop(); 41 q.push(x); 42 vis[x]=1; 43 dis[x]=0; 44 while(!q.empty()) 45 { 46 int u=q.front(); 47 q.pop(); 48 for(int i=head[u];i!=-1;i=edge[i].next) 49 { 50 int v=edge[i].v; 51 if(vis[v]) 52 continue; 53 q.push(v); 54 vis[v]=1; 55 dis[v]=dis[u]+edge[i].c; 56 } 57 } 58 } 59 60 void dfs(int u,int fa){ 61 d[u]=d[fa]+1; 62 p[u][0]=fa; 63 for(int i=1;i<POW;i++) p[u][i]=p[p[u][i-1]][i-1]; 64 for(int i=head[u];i!=-1;i=edge[i].next){ 65 int v=edge[i].v; 66 if(v==fa) continue; 67 dfs(v,u); 68 } 69 } 70 71 int lca( int a, int b ){ 72 if( d[a] > d[b] ) a ^= b, b ^= a, a ^= b; 73 if( d[a] < d[b] ){ 74 int del = d[b] - d[a]; 75 for( int i = 0; i < POW; i++ ) if(del&(1<<i)) b=p[b][i]; 76 } 77 if( a != b ){ 78 for( int i = POW-1; i >= 0; i-- ) 79 if( p[a][i] != p[b][i] ) 80 a = p[a][i] , b = p[b][i]; 81 a = p[a][0], b = p[b][0]; 82 } 83 return a; 84 } 85 86 void LCA(int n) 87 { 88 clr(p,0); 89 d[1]=0; 90 dfs(1,1); 91 92 bfs(1); 93 94 int k; 95 scanf("%d",&k); 96 int u,v; 97 rep(i,1,k){ 98 scanf("%d%d",&u,&v); 99 printf("%d\n",dis[u]+dis[v]-2*dis[lca(u,v)]); 100 } 101 } 102 103 int main() 104 { 105 int n,m; 106 scanf("%d%d",&n,&m); 107 init(); 108 rep(i,1,m){ 109 int u,v,c; 110 scanf("%d%d%d%*s",&u,&v,&c); 111 add(u,v,c); 112 add(v,u,c); 113 } 114 115 LCA(n); 116 return 0; 117 }
又用tarjin离线做了一遍= =
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 #define rep(i,a,b) for(int i=a;i<=b;i++) 6 #define clr(a,m) memset(a,m,sizeof(a)) 7 using namespace std; 8 9 const int MAXN=44444; 10 11 struct Edge{ 12 int v,next,c; 13 Edge(){} 14 Edge(int _v,int _c,int _next):v(_v),c(_c),next(_next){} 15 }edge[MAXN<<1]; 16 17 struct EDGE{ 18 int u,v; 19 int ans; 20 EDGE(){} 21 EDGE(int _u,int _v):u(_u),v(_v),ans(-1){} 22 }; 23 24 int head[MAXN],tol; 25 int p[MAXN],vis[MAXN],dis[MAXN]; 26 27 queue<int>q; 28 vector<int>query[MAXN]; 29 vector<EDGE>G; 30 31 void init() 32 { 33 tol=0; 34 clr(head,-1); 35 } 36 37 void add(int u,int v,int c) 38 { 39 edge[tol]=Edge(v,c,head[u]); 40 head[u]=tol++; 41 } 42 43 void build(int m) 44 { 45 init(); 46 rep(i,1,m){ 47 int u,v,c; 48 scanf("%d%d%d%*s",&u,&v,&c); 49 add(u,v,c); 50 add(v,u,c); 51 } 52 53 int k; 54 scanf("%d",&k); 55 rep(i,1,k){ 56 int u,v,siz; 57 scanf("%d%d",&u,&v); 58 59 G.push_back(EDGE(u,v)); 60 siz=G.size(); 61 query[u].push_back(siz-1); 62 63 G.push_back(EDGE(v,u)); 64 siz=G.size(); 65 query[v].push_back(siz-1); 66 } 67 } 68 69 void bfs(int x) 70 { 71 clr(vis,0); 72 clr(dis,0); 73 while(!q.empty()) 74 q.pop(); 75 q.push(x); 76 vis[x]=1; 77 dis[x]=0; 78 while(!q.empty()) 79 { 80 int u=q.front(); 81 q.pop(); 82 for(int i=head[u];i!=-1;i=edge[i].next) 83 { 84 int v=edge[i].v; 85 if(vis[v]) 86 continue; 87 q.push(v); 88 vis[v]=1; 89 dis[v]=dis[u]+edge[i].c; 90 } 91 } 92 } 93 94 int find(int x) 95 { 96 return (x==p[x])?x:(p[x]=find(p[x])); 97 } 98 99 void dfs(int x) 100 { 101 vis[x]=1; 102 for(int i=head[x];i!=-1;i=edge[i].next) 103 { 104 int v=edge[i].v; 105 if(vis[v]) 106 continue; 107 dfs(v); 108 p[v]=x; 109 } 110 111 int siz =query[x].size()-1; 112 rep(i,0,siz) 113 { 114 int t=query[x][i]; 115 if(vis[G[t].v]){ 116 G[t].ans=find(G[t].v); 117 } 118 } 119 } 120 121 void LCA(int rt,int n) 122 { 123 clr(vis,0); 124 rep(i,1,n) 125 p[i]=i; 126 dfs(rt); 127 } 128 129 void PRT() 130 { 131 int siz=G.size(); 132 for(int i=0;i<siz;i+=2) 133 { 134 int u=G[i].u; 135 int v=G[i].v; 136 if(G[i].ans!=-1) 137 printf("%d\n",dis[u]+dis[v]-2*dis[G[i].ans]); 138 else 139 printf("%d\n",dis[u]+dis[v]-2*dis[G[i^1].ans]); 140 } 141 } 142 143 int main() 144 { 145 int n,m; 146 scanf("%d%d",&n,&m); 147 build(m); 148 bfs(1); 149 LCA(1,n); 150 PRT(); 151 return 0; 152 }