随笔-14  评论-21  文章-0  trackbacks-0

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;
}

posted on 2011-05-05 16:19 zxb 阅读(286) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理