题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2539
裸的匹配吧?那就直接跑sap就好了。。。(PS:数据貌似有重复描述缘分的,按后面一个计算)
代码:
#include
#include
#include
#include
#include
using namespace std ;
#define MAXN 210
#define inf 0x7fffffff
struct edge{
edge *next ,*pair ;
int t , f , c ;
}*head[ MAXN ];
void Add(int s ,int t ,int f ,int c ){
edge *p =new( edge );
p -> t = t , p -> f = f , p -> c = c , p -> next = head[ s ];
head[ s ]= p ;
}
void AddEdge(int s ,int t ,int f ,int c ){
Add( s , t , f , c ),Add( t , s ,0,- c );
head[ s ]-> pair = head[ t ], head[ t ]-> pair = head[ s ];
}
int S , T ;
int value[ MAXN ][ MAXN ], n , k , pos[ MAXN ][2];
string Name[ MAXN ];
string Change( string st ){
string s = st ;
for(int i =0; i < s.size( ); i ++)if( s[ i ]>='A'&& s[ i ]<='Z'){
s[ i ]= s[ i ]+('a'-'A');
}
return s ;
}
int Find( string s ){
for(int i =0; i ++< n *2;)if( Name[ i ]== s )return i ;
}
bool check(int x0 ,int y0 ,int x1 ,int y1 ,int t0 ,int t1 ){
if(( x0 - x1 )*( x0 - x1 )+( y0 - y1 )*( y0 - y1 )> k )return false;
for(int i =0; i ++<2* n ;)if( i != t0 && i != t1 ){
if( pos[ i ][0]>=min( x0 , x1 )&& pos[ i ][0]<=max( x0 , x1 )){
if( pos[ i ][1]>=min( y0 , y1 )&& pos[ i ][1]<=max( y0 , y1 )){
int X1 = pos[ i ][0]- x0 , Y1 = pos[ i ][1]- y0 ;
int X2 = pos[ i ][0]- x1 , Y2 = pos[ i ][1]- y1 ;
if( X1 * Y2 == X2 * Y1 )return false;
}
}
}
return true;
}
int dist[ MAXN ], cost =0;
bool f[ MAXN ];
int aug(int v ,int flow ){
if( v == T ){
cost += dist[ T ]* flow ;
return flow ;
}
int rec =0; f[ v ]=false;
for( edge *p = head[ v ]; p ; p = p -> next )if( p ->f && f[ p -> t ]&& dist[ p -> t ]== dist[ v ]+ p -> c ){
int ret =aug( p -> t ,min( flow - rec , p -> f ));
p -> f -= ret , p -> pair -> f += ret ;
if(( rec += ret )== flow )return flow ;
}
return rec ;
}
queue Q ;
bool spfa( ){
for(int i =0; i ++< T ;) dist[ i ]=- inf , f[ i ]=false;
while(! Q.empty( )) Q.pop( );
dist[ S ]=0, Q.push( S ), f[ S ]=true;
while(! Q.empty( )){
int v = Q.front( ); Q.pop( ); f[ v ]=false;
for( edge *p = head[ v ]; p ; p = p -> next )if( p -> f && dist[ p -> t ]< dist[ v ]+ p -> c ){
dist[ p -> t ]= dist[ v ]+ p -> c ;
if(! f[ p -> t ]){
f[ p -> t ]=true; Q.push( p -> t );
}
}
}
return dist[ T ]>- inf ;
}
void costflow( ){
while(spfa( )){
do{
memset( f ,true,sizeof( f ));
}while(aug( S , inf ));
}
}
int main( ){
cin >> k >> n ; k *= k ;
for(int i =0; i ++< n *2;){
cin >> pos[ i ][0]>> pos[ i ][1]>> Name[ i ];
Name[ i ]=Change( Name[ i ]);
}
for(int i =0; i ++< n *2;)for(int j =0; j ++< n *2;) value[ i ][ j ]=1;
string s ;
for( cin >> s ; s !="End"; cin >> s ){
int x ; string s0 ;
cin >> s0 >> x ;
s =Change( s ); s0 =Change( s0 );
int y =Find( s ), z =Find( s0 );
value[ y ][ z ]= value[ z ][ y ]= x ;
}
memset( head ,0,sizeof( head ));
S = n *2+1, T = n *2+2;
for(int i =0; i ++< n ;)AddEdge( S , i ,1,0);
for(int i = n ; i ++< n *2;)AddEdge( i , T ,1,0);
for(int i =0; i ++< n ;)for(int j = n ; j ++< n *2;){
if(check( pos[ i ][0], pos[ i ][1], pos[ j ][0], pos[ j ][1], i , j )){
AddEdge( i , j ,1, value[ i ][ j ]);
}
}
costflow( );
cout << cost << endl ;
return 0;
}