求出最大生成树之后求LCA即可。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <stdio.h> #include <iomanip> #include <algorithm> #include <string> #include <cstring> #include <cmath> #include <map> #include <queue> #include <vector> #define MOD 1000000007 using namespace std; const int MAXN = 250005; typedef long long LL; const LL INF = 0x3f3f3f3f3f3f3f3fLL; const LL DEG = 30; struct SEdge { LL end; LL next; LL value; }edge[MAXN*2]; LL head[MAXN], CntEdge1, CntEdge; LL Dist[MAXN]; LL Pre[MAXN][DEG]; LL Ans[MAXN]; bool Visited[MAXN]; LL pre[MAXN]; struct SMEdge { LL start; LL end; LL value; bool operator < ( const SMEdge &a ) const { return value < a.value; } }edge1[MAXN*2]; LL Father[MAXN]; void Initial() { memset( head, -1, sizeof(head) ); memset( Visited, false, sizeof(Visited) ); memset( Pre, 0, sizeof(Pre) ); memset( Dist, 0, sizeof(Dist) ); memset( Father, 0, sizeof(Father) ); CntEdge = CntEdge1 = 0; } void AddEdge1( LL start, LL end, LL value ) { edge1[CntEdge1].start = start; edge1[CntEdge1].end = end; edge1[CntEdge1].value = value; CntEdge1++; } void AddEdge( LL start, LL end, LL value ) { edge[CntEdge].end = end; edge[CntEdge].value = value; edge[CntEdge].next = head[start]; head[start] = CntEdge++; } LL Find( LL x ) { return Father[x]?Father[x]=Find(Father[x]):x; } void Unite( LL u, LL v ) { if( Find(u) != Find(v) ) Father[Find(u)] = Find(v); } void Kruskal() { sort( edge1, edge1 + CntEdge1 ); for( LL i = 0; i < CntEdge1; i++ ) { LL Left = edge1[i].start; LL Right = edge1[i].end; LL value = 1; if( Find(Left) != Find(Right) ) { Unite(Left, Right); AddEdge( Left, Right, value ); AddEdge( Right, Left, value ); } } } void DFS( LL Now ) { for( LL j = 1; j < DEG; j++ ) Pre[Now][j] = Pre[Pre[Now][j-1]][j-1]; Visited[Now] = true; for( LL i = head[Now]; i != -1; i = edge[i].next ) { LL temp = edge[i].end; if( Visited[temp] ) continue; pre[temp]=Now; Dist[temp] = Dist[Now] + edge[i].value; Pre[temp][0] = Now; DFS( temp ); } } LL LCA( LL node1, LL node2 ) { LL i; if( Dist[node1] < Dist[node2] ) swap( node1, node2 ); for( LL i = 0, d=Dist[node1]-Dist[node2]; d; i++, d>>=1 ) { if( d&1 ) node1 = Pre[node1][i]; } if( node1 == node2 ) return node1; for( LL i = DEG-1; i >= 0; i-- ) if( Pre[node1][i] != Pre[node2][i] ) node1 = Pre[node1][i], node2 = Pre[node2][i]; return Pre[node1][0]; } LL Distance( LL node1, LL node2 ) { return Dist[node1] + Dist[node2] - 2*Dist[LCA(node1, node2)]; } int main() { LL N, M; while( scanf("%lld %lld", &N, &M) != EOF ) { Initial(); for( LL i = 0; i < N; i++ ) for( LL j = 1; j <= M; j++ ) { char D[3], R[3]; LL a, b; scanf("%s %lld %s %lld", D, &a, R, &b); LL start = j+i*M; LL end; if( D[0] != 'X' ) { end = start + M; AddEdge1( start, end, -a ); } if( R[0] != 'X' ) { end = start + 1; AddEdge1( start, end, -b ); } } Kruskal(); DFS(1); LL Q; scanf("%lld", &Q); for( LL i = 0; i < Q; i++ ) { LL x1, x2, y1, y2; LL P1, P2; scanf("%lld %lld %lld %lld", &x1, &y1, &x2, &y2); P1 = y1+(x1-1)*M; P2 = y2+(x2-1)*M; Ans[i] = Distance(P1, P2); } for( LL i = 0; i < Q; i++ ) printf("%lld\n", Ans[i]); } return 0; }