#include #include #include #include using namespace std; struct edge { int a,b,c; }; int n,m,q; edge edges[1000111]; vector Graph[500111]; bool TFO[500111]; int father[500111]; vector colors[500111]; int depth[500111]; ///LCA int IDCounter = 0; int verID[500111]; int IDToVer[500111]; int IT[4000111]; int LEAFOFFSET; int Len = 0; int FirstSeen[500111]; void DFS(int ver,int dad) { TFO[ver] = true; father[ver] = dad; depth[ver] = depth[dad] + 1; IDCounter++; verID[ver] = IDCounter; IDToVer[IDCounter] = ver; Len++; IT[Len+LEAFOFFSET] = verID[ver]; FirstSeen[ver] = Len; int i; for (i=0;i 1) { if (L % 2 == 0) val = MIN(val, IT[L+1]); if (R % 2 == 1) val = MIN(val, IT[R-1]); L /= 2; R /= 2; } return val; } int getLCA(int a,int b) { if (FirstSeen[a] > FirstSeen[b]) return getLCA(b,a); return IDToVer[ getMin(FirstSeen[a], FirstSeen[b]) ]; } struct hit { int hitCtr, forceColor, node; }; hit make_hit(int a,int b,int c) { hit v; v.hitCtr = a; v.node = b; v.forceColor = c; return v; } hit fHit[500111][3][20]; hit computeHit(int ver,int opt,int dad) { if (opt == 2) { if (colors[dad].size() == 1) return make_hit(0, dad, 0); else return make_hit(0, dad, 2); } else { if (colors[dad].size() == 1) { if (colors[ver][opt] == colors[dad][0]) return make_hit(1, dad, 0); else return make_hit(0, dad, 0); } else if (colors[dad].size() == 2) { if (colors[ver][opt] == colors[dad][0]) return make_hit(0, dad, 1); else if (colors[ver][opt] == colors[dad][1]) return make_hit(0, dad, 0); else return make_hit(0, dad, 2); } else return make_hit(0, dad, 2); } } hit recHit(int ver,int opt,int level) { int totalhits = 0; hit h = fHit[ver][opt][level-1]; totalhits += h.hitCtr; h = fHit[h.node][h.forceColor][level-1]; return make_hit(totalhits + h.hitCtr, h.node, h.forceColor); } void solveBlocks(int ver) { TFO[ver] = true; int i; int dad = father[ver]; if (depth[ver] <= 2) { for (i=0;i<=19;i++) { fHit[ver][0][i] = make_hit(0, 1, 2); fHit[ver][1][i] = make_hit(0, 1, 2); fHit[ver][2][i] = make_hit(0, 1, 2); } } else { if (colors[ver].size() > 2) { fHit[ver][2][0] = computeHit(ver, 2, dad); fHit[ver][1][0] = fHit[ver][2][0]; fHit[ver][0][0] = fHit[ver][2][0]; } else { fHit[ver][0][0] = computeHit(ver, 0, dad); if (colors[ver].size() == 2) { fHit[ver][1][0] = computeHit(ver, 1, dad); fHit[ver][2][0] = computeHit(ver, 2, dad); } else { fHit[ver][1][0] = fHit[ver][0][0]; fHit[ver][2][0] = fHit[ver][0][0]; } } //cout< 2) { fHit[ver][2][i] = recHit(ver, 2, i); fHit[ver][1][i] = fHit[ver][2][i]; fHit[ver][0][i] = fHit[ver][2][i]; } else { fHit[ver][0][i] = recHit(ver, 0, i); if (colors[ver].size() == 2) { fHit[ver][1][i] = recHit(ver, 1, i); fHit[ver][2][i] = recHit(ver, 2, i); } else { fHit[ver][1][i] = fHit[ver][0][i]; fHit[ver][2][i] = fHit[ver][0][i]; } } //cout<=0;i--) { if ( depth[ fHit[ver][opt][i].node ] > depth[upVer] ) { //cout<<"successfully taking "< 2) return; int i; for (i=0;i=1;i--) { IT[i] = MIN(IT[2*i], IT[2*i+1]); } for (i=1;i<=m;i++) { if (father[ edges[i].a ] == edges[i].b) addColor(edges[i].a,edges[i].c); else addColor(edges[i].b,edges[i].c); } memset(TFO,false,sizeof(TFO)); solveBlocks(1); scanf("%d",&q); for (i=1;i<=q;i++) { scanf("%d %d",&a,&b); if (a == b) { printf("0\n"); continue; } lca = getLCA(a,b); //cout<<"lca = "<