题目大意
给定坐标系内的
n
个两两不同的点。
现在可以任意将这些点的
Data Constraint
n≤50
题解
考虑费用流。
将
X
和
假如原图有一个点
(x,y)
那就
x→y
连一条费用为
1
容量为
最后跑一遍费用流。
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std ;
#define N 50 + 10
#define M 100000 + 10
struct Point {
int x , y ;
Point ( int X = 0 , int Y = 0 ) { x = X , y = Y ; }
} P[N] ;
struct Note {
int v , h ;
} tpx[N] , tpy[N] ;
bool Map[N][N] , vis[2*N] ;
int Node[4*M] , Next[4*M] , Head[2*M] , C[2*M] , Cost[2*M] , tot = 1 ;
int Numx[N] , Numy[N] , D[M] , Dist[2*N] , Pre[M] ;
int n , ans , Cntx , Cnty , S , T ;
bool cmp( Note a , Note b ) { return a.v < b.v ; }
void PreX() {
sort( tpx + 1 , tpx + n + 1 , cmp ) ;
Cntx = 0 ;
for (int i = 1 ; i <= n ; i ++ ) {
if ( tpx[i].v != tpx[i-1].v ) ++ Cntx ;
P[tpx[i].h].x = Cntx ;
Numx[Cntx] ++ ;
}
}
void PreY() {
sort( tpy + 1 , tpy + n + 1 , cmp ) ;
Cnty = 0 ;
for (int i = 1 ; i <= n ; i ++ ) {
if ( tpy[i].v != tpy[i-1].v ) ++ Cnty ;
P[tpy[i].h].y = Cnty ;
Numy[Cnty] ++ ;
}
}
void link( int u , int v , int w , int cost ) {
Node[++tot] = v , Next[tot] = Head[u] , C[tot] = w , Cost[tot] = cost , Head[u] = tot ;
Node[++tot] = u , Next[tot] = Head[v] , C[tot] = 0 , Cost[tot] = -cost , Head[v] = tot ;
}
bool SPFA() {
int i = 0 , j = 1 ;
memset( Dist , 63 , sizeof(Dist) ) ;
D[1] = S ;
Dist[S] = 0 ;
vis[S] = 1 ;
while ( i < j ) {
i ++ ;
int now = D[i] ;
for (int p = Head[now] ; p ; p = Next[p] ) {
if ( !C[p] ) continue ;
if ( Dist[now] + Cost[p] < Dist[Node[p]] ) {
Dist[Node[p]] = Dist[now] + Cost[p] ;
Pre[Node[p]] = p ;
if ( !vis[Node[p]] ) {
D[++j] = Node[p] ;
vis[Node[p]] = 1 ;
}
}
}
vis[now] = 0 ;
}
return Dist[T] < Dist[T+1] ;
}
int main() {
freopen( "chess.in" , "r" , stdin ) ;
freopen( "chess.out" , "w" , stdout ) ;
scanf( "%d" , &n ) ;
for (int i = 1 ; i <= n ; i ++ ) {
scanf( "%d%d" , &P[i].x , &P[i].y ) ;
tpx[i].v = P[i].x , tpx[i].h = i ;
tpy[i].v = P[i].y , tpy[i].h = i ;
}
PreX() , PreY() ;
S = 0 , T = Cntx + Cnty + 1 ;
for (int i = 1 ; i <= n ; i ++ ) Map[P[i].x][P[i].y] = 1 ;
for (int i = 1 ; i <= Cntx ; i ++ ) {
for (int j = 1 ; j <= Cnty ; j ++ ) {
link( i , Cntx + j , 1 , Map[i][j] ) ;
}
}
for (int i = 1 ; i <= Cntx ; i ++ ) link( S , i , Numx[i] , 0 ) ;
for (int i = 1 ; i <= Cnty ; i ++ ) link( Cntx + i , T , Numy[i] , 0 ) ;
while ( SPFA() ) {
int Minv = 0x7FFFFFFF ;
for (int x = T ; x != S ; x = Node[Pre[x]^1] ) Minv = min( Minv , C[Pre[x]] ) ;
ans += Minv * Dist[T] ;
for (int x = T ; x != S ; x = Node[Pre[x]^1] ) {
C[Pre[x]] -= Minv ;
C[Pre[x]^1] += Minv ;
}
}
printf( "%d\n" , ans ) ;
return 0 ;
}
以上.