TOJ 3345 Chinese Chess 二分匹配 匈牙利算法 扩展

TOJ 3345 Chinese Chess 二分匹配 匈牙利算法 扩展

TOJ  3345  Chinese Chess http://acm.tju.edu.cn/toj/showp3345.html
双链表实习双向邻接表,正向图反向图,匈牙利匹配后,枚举删除匹配边,两边做重新查找增广路操作,如果都没法查到则证明是重要边,还原原匹配时候要注意细节。

优化1:求最大匹配时候先能匹配就匹配上。
优化2:标记已经确定不是必要点的行和列 flag[]和flag2[]
注意1:删除匹配边后 应在匹配边的两面点 分别查询
注意2:没查到新匹配要还原匹配边

#include
< stdio.h >
#include
< string .h >
const   int  size2  =   100110 ;
const   int  size1  =   10110 ;
int  n , m , k ;
struct  node{
    node 
* p;
    node 
* q;
    
int  v;
    
int  v2;
};
int  val;

node edg[size2];

bool  visit[size1];
int  pp[size1];
bool  flag[size1];
bool  flag2[size1];

node 
* g[size1];
node 
* g1[size1];

int  ppre[size1];
int  ppr[size1];

int  nxy[size1];
inline 
bool  check( int  x ,  int  y ,  int  fc){
    node 
* now  =  g[x];
    
while (now  !=  NULL){
        
if (now -> ==  y){
            
if (fc  ==   0 )
                
return   true ;
            
if (fc  ==   1 ){
                now
-> =   - 1 ;
                
return   true ;
            }
            
if (fc  ==   2 ){
                now
-> =  val;
                
return   true ;
            }
        }
        
else {
            now 
=  now -> p;
        }
    }
    
return   false ;
}

inline 
bool  check2( int  x ,  int  y ,  int  fc){
    node 
* now  =  g1[x];
    
while (now  !=  NULL){
        
if (now -> v2  ==  y){
            
if (fc  ==   0 )
                
return   true ;
            
if (fc  ==   1 ){
                now
-> v2  =   - 1 ;
                
return   true ;
            }
            
if (fc  ==   2 ){
                now
-> v2  =  val;
                
return   true ;
            }
        }
        
else {
            now 
=  now -> q;
        }
    }
    
return   false ;
}
inline 
bool  find( int  a){
    node 
* now  =  g[a];
    
while (now  !=  NULL){
             
int  i  =  now -> v;
             
if (i  !=   - 1 ){
                 
if ( ! visit[i] ){
                    visit[i] 
=   true ;
                    
if (pp[i]  ==   - 1   || find(pp[i])){
                        pp[i] 
=  a;
                        nxy[a] 
=  i;
                        
return   true ;
                    }
                }
             }
            now 
=  now -> p;
    }
    
return   false ;
}

inline 
bool  find2( int  a){
    node 
* now  =  g1[a];
    
while (now  !=  NULL){
             
int  i  =  now -> v2;
             
if (i  !=   - 1 ){
                 
if ( ! visit[i] ){
                    visit[i] 
=   true ;
                    
if (nxy[i]  ==   - 1   || find2(nxy[i])){
                        nxy[i] 
=  a;
                        pp[a] 
=  i;
                        
return   true ;
                    }
                }
             }
            now 
=  now -> q;
    }
    
return   false ;
}

void  output(){
    printf(
" \n\n " );
    
for int  i  =   1  ; i  <=  m ; i ++ )
        printf(
" %d -> %d\n " ,pp[i],i);
        printf(
" \n " );
    
for int  i  =   1  ; i  <=  n ; i ++ )
        printf(
" %d -> %d\n " ,i,nxy[i]);
    printf(
" \n\n " );
}

void  output1( int  x){
    node 
* now  =  g1[x];
    
while (now  !=  NULL){
             
int  i  =  now -> v2;

             printf(
"   %d " ,i);
            now 
=  now -> q;
    }
    printf(
" \n " );
}

int  main(){
        
int  a1,i,a2;
        
int  _case  =   0 ;
        
int  num;
        
while (scanf( " %d%d%d " , & n, & m, & k) != EOF){
            num 
=   0 ;
            memset(g,
0 , sizeof (g));
            memset(g1,
0 , sizeof (g1));
            memset(pp,
- 1 , sizeof (pp));
            memset(nxy,
- 1 , sizeof (nxy));
            
for (i  =   1 ; i  <=  k ; i ++ ){
                scanf(
" %d%d " , & a1, & a2);
                
if (check(a1,a2, 0 ))  continue ;
                edg[i].v 
=  a2;
                edg[i].v2 
=  a1;
                edg[i].p 
=  NULL;
                edg[i].q 
=  NULL;

                
if (g[a1]  ==  NULL){
                    g[a1] 
=   & edg[i];
                }
else {
                    edg[ppre[a1]].p 
=   & edg[i];
                }

                
if (g1[a2]  ==  NULL){
                    g1[a2] 
=   & edg[i];
                }
else {
                    edg[ppr[a2]].q 
=   & edg[i];
                }

                ppre[a1] 
=  i ;
                ppr[a2] 
=  i ;

                
if (pp[a2]  ==   - 1   &&  nxy[a1]  ==   - 1 ){
                    pp[a2] 
=  a1;
                    nxy[a1] 
=  a2;
                    num
++ ;
                }
            }
            
for (i  =   1  ; i  <=  m ; i ++ ){
                
if (pp[i]  ==   - 1 ){
                    memset(visit,
0 , sizeof (visit));
                    
if (find2(i)){
                        num
++ ;
                    }
                }
            }
            memset(flag,
0 , sizeof (flag));
            memset(flag2,
0 , sizeof (flag2));
            
int  ans  =   0 ;
            
for (i  =   1  ; i  <=  m ; i ++ ){
                
if (pp[i]  !=   - 1 ){
                    
int  key  =   0 ;
                    
int  now  =  pp[i];
                    pp[i] 
=   - 1  ;
                    nxy[now] 
=   - 1 ;
                    
if (flag[pp[i]]  ==   0 ){
                        check(now,i,
1 );
                        memset(visit,
0 , sizeof (visit));
                        
if (find(now)){
                            key 
=   1 ;
                        }
                        val 
=  i ;
                        check(now,
- 1 , 2 );
                    }

                    
if (flag2[i]  ==   0   &&  key  ==   0  ){
                        check2(i,now,
1 );
                        memset(visit,
0 , sizeof (visit));
                        
if (find2(i)){
                            key 
=   1 ;
                        }
                        val 
=  now ;
                        check2(i,
- 1 , 2 );
                    }
                     
if ( ! key){
                            ans
++ ;
                                nxy[now] 
=  i;
                            pp[i] 
=  now;
                     }
                     
else {
                        flag[now] 
=   1  ;
                        flag2[i] 
=   1  ;
                     }
                }
// 右侧有边
            }
            printf(
" Board %d have %d important blanks for %d chessmen.\n " , ++ _case,ans,num);
        }
    
return   0 ;
}

你可能感兴趣的:(TOJ 3345 Chinese Chess 二分匹配 匈牙利算法 扩展)