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 }
View Code

 又用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 }
View Code

 

 

 

posted @ 2013-08-15 09:31  Thousand Sunny  阅读(311)  评论(0编辑  收藏  举报