2018徐州网络赛J

求出最大生成树之后求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;
}
View Code

猜你喜欢

转载自www.cnblogs.com/LMissher/p/9615354.html