Pagini recente » Cod sursa (job #107341) | Cod sursa (job #2951112) | Cod sursa (job #1592248) | Cod sursa (job #66917) | Cod sursa (job #1710149)
#include <bits/stdc++.h>
using namespace std;
class DSU
{
public:
DSU( const int _N )
{
N = _N;
Father = vector<int>( N + 1, 0 );
Rank = vector<int> ( N + 1, 0 );
initialise();
}
void initialise()
{
for ( int i = 1; i <= N; ++i )
{
Father[i] = i;
Rank[i] = 1;
}
}
int Find( int node )
{
int root = node, auxNode;
while ( Father[ root ] != root )
root = Father[ root ];
while ( root != Father[ node ] )
{
auxNode = Father[ node ];
Father[ node ] = root;
node = auxNode;
}
return root;
}
int Check( int x, int y )
{
return ( Find( x ) == Find( y ) );
}
void Union( int x, int y )
{
int fx = Find( x );
int fy = Find( y );
if ( fx != fy )
{
x = fx; y = fy;
if ( Rank[x] < Rank[y] )
Father[x] = y;
else
Father[y] = x;
if ( Rank[x] == Rank[y] )
Rank[y]++;
}
}
private:
vector <int> Father, Rank;
int N;
};
const int Nmax = 100000 + 1;
const int INF = 0x3f3f3f3f;
struct Edge
{
int a, b, c;
bool operator < ( const Edge &E ) const
{
return c < E.c;
}
} Edges[8 * Nmax];
int neighbor[Nmax];
int distToNeighbor[Nmax];
int ind[Nmax];
int X[Nmax], Y[Nmax];
int N, nrEdges;
bool cmp1( const int a, const int b )
{
if ( Y[a] != Y[b] )
return Y[a] < Y[b];
else
return X[a] < X[b];
}
bool cmp2( const int a, const int b )
{
return Y[a] - X[a] < Y[b] - X[b];
}
void solve( int st, int dr )
{
if ( dr - st <= 1 )
return;
int m = ( st + dr ) / 2;
solve( st, m );
solve( m, dr );
int distToNeigh = INF;
int neigh = -1;
for ( int i = st, j = m; i < m; ++i )
{
while ( j < dr && Y[ ind[j] ] - X[ ind[j] ] <= Y[ ind[i] ] - X[ ind[i] ] )
{
if ( distToNeigh > X[ ind[j] ] + Y[ ind[j] ] )
{
distToNeigh = X[ ind[j] ] + Y[ ind[j] ];
neigh = ind[j];
}
j++;
}
if ( distToNeighbor[ ind[i] ] > distToNeigh )
{
distToNeighbor[ ind[i] ] = distToNeigh;
neighbor[ ind[i] ] = neigh;
}
}
inplace_merge( ind + st, ind + m, ind + dr, cmp2 );
}
int main()
{
ifstream in("metrou4.in");
ofstream out("metrou4.out");
ios_base::sync_with_stdio( false );
int T;
in >> T;
while (T--)
{
in >> N;
nrEdges = 0;
memset(X, 0, sizeof X);
memset(Y, 0, sizeof Y);
memset(distToNeighbor, 0, sizeof distToNeighbor);
memset(ind, 0, sizeof ind);
memset(neighbor, 0, sizeof neighbor);
for ( int i = 0; i < N; ++i )
in >> X[i] >> Y[i];
for ( int octant = 0; octant < 8; ++octant )
{
memset( distToNeighbor, 0x3f, sizeof( distToNeighbor ) );
memset( neighbor, -1, sizeof( neighbor ) );
for ( int i = 0; i < N; ++i )
ind[i] = i;
sort( ind, ind + N, cmp1 );
solve( 0, N );
for ( int i = 0; i < N; ++i )
if ( ~neighbor[i] )
{
int c = abs( X[i] - X[ neighbor[i] ] ) + abs( Y[i] - Y[ neighbor[i] ] );
Edges[ ++nrEdges ] = Edge{ i + 1, neighbor[i] + 1, c };
}
if ( octant & 1 )
{
for ( int i = 0; i < N; ++i )
X[i] = -X[i];
}
else
{
for ( int i = 0; i < N; ++i )
swap( X[i], Y[i] );
}
}
DSU D( N );
sort( Edges + 1, Edges + nrEdges + 1 );
long long sol = 0;
for ( int i = 1; i <= nrEdges; ++i )
{
if ( D.Check( Edges[i].a, Edges[i].b ) == false )
{
sol += Edges[i].c;
D.Union( Edges[i].a, Edges[i].b );
}
}
out << sol << "\n";
}
return 0;
}