POJ Challenge 超级笔记

POJ Challenge 超级笔记

http://poj.openjudge.cn/practice/1013/

标准做法应该要用正则图的性质,找欧拉回路。
但是我用贪心+匈牙利算法直接就过了,速度也很快(<1s)。


贪心就是每给出一条边,如果这条边的两端都没有被匹配,则先匹配它们。
由于没有直接给出二分图的形式,所以我对每个没有被匹配点都找了一次增广链。


#include  < iostream >
#include 
< cstdlib >
#include 
< cstdio >

using   namespace  std;

const   int  N = 100000 ;

int  n,m,r,l[N + 5 ],to[N * 20 + 5 ],next[N * 20 + 5 ],match[N + 5 ],q[N + 5 ];
bool  b[N + 5 ];

bool  find( int  i)
{
    
int j,k,t;
    k
=l[i];
    
while(k)
    
{
        j
=to[k];
        
if (!b[j])
        
{
            t
=match[j];
            match[j]
=i;
            b[j]
=true;
            q[
++r]=j;
            
if (!t||find(t))
            
{
                match[i]
=j;
                
return true;
            }

            match[j]
=t;
        }

        k
=next[k];
    }

    
return false;
}


int  main( void )
{
    
int i,j,k,n,m,sum=0;
    scanf(
"%d%d",&n,&m);
    k
=0;
    
while(m--)
    
{
        scanf(
"%d%d",&i,&j);
        
if (!match[i]&&!match[j])
        
{
            match[i]
=j;
            match[j]
=i;
            
++sum;
        }

        to[
++k]=j;
        next[k]
=l[i];
        l[i]
=k;
        to[
++k]=i;
        next[k]
=l[j];
        l[j]
=k;
    }

    
for(i=1;i<=n;++i)
        
if (!match[i])
        
{
            r
=0;
            
if (find(i))
                
++sum;
            
for(j=1;j<=r;++j)
                b[q[j]]
=false;
        }

    
for(i=1;i<=n;++i)
        
if (match[i]>i)
            printf(
"%d %d\n",i,match[i]);
    
return 0;
}

你可能感兴趣的:(POJ Challenge 超级笔记)