POJ 1274 网络流最大匹配

用的FF算法,裸实现516ms++,记得当年的二分图16ms啊....

这里发两个模板吧,网络流才初学.. 弱爆了....

#include<iostream>
#include<cstdio>
#include<cmath>
#define MN 422
using namespace std;

struct edge
{	int f,c;	}g[MN][MN];
struct node
{	int l,p,a;	}list[MN];

int s,t,ans,M,N;

void init()
{
 	 s=1;t=N+M+2;ans=0;
 	 memset( g,0,sizeof(g) );
 	 for( int i=1;i<=N;i++ )
 	 {
	  	  g[s][i+1].c=1;
	  	  int n,u;
	  	  scanf( "%d",&n );
	  	  for( int j=1;j<=n;j++ )
	  	  {
	  	  	   scanf( "%d",&u );
	  	  	   g[i+1][N+u+1].c=1;
   		  }
	 }
	 for( int i=1;i<=M;i++ )
	 	  g[i+N+1][t].c=1;
}

int find()
{
 	int i=1;
 	while( i<=N+M+2&&(list[i].l==0||list[i].p!=0) )i++;
 	if( i>N+M+2 ) return 0;
 	else return i;
}

bool ford()
{
 	 memset( list,0,sizeof(list) );
 	 list[s].l=s;
 	 list[s].a=9999999;
 	 while( list[t].l==0 )
 	 {
	  		int i=find();
	  		if( i==0 ) return true;
	  		for( int j=1;j<=N+M+2;j++ )
	  		{
			 	 if( list[j].l==0 &&( g[j][i].c||g[i][j].c ) )
			 	 {
				  	 if( g[i][j].c-g[i][j].f )
				  	 {
					  	 list[j].l=i;
					  	 list[j].a=min(list[i].a,g[i][j].c-g[i][j].f);
					 }
					 if( g[j][i].f>0 )
					 {
					  	 list[j].l=-i;
					  	 list[j].a=min(list[i].a,g[j][i].f );
	 		  		 }
 			  	 }
 	 	 	}
 	 	 	list[i].p=1;
	 }
 	 ans+=list[t].a;
 	 return false;
}
void change()
{
 	 int j,m,a;
 	 m=t;a=list[t].a;
 	 while( m!=s )
 	 {
	  		j=m;m=abs(list[j].l);
	  		if( list[m].l>0 ) g[m][j].f+=a;
	  		if( list[m].l<0 ) g[j][m].f-=a;
	 }
}

void work()
{
 	 bool p;
 	 while(1)
 	 {	
	 	p=ford();
		 if( p )
		 	 break;
		 else change();
	 }
	 printf( "%d\n",ans );
}

int main()
{
 	while( scanf("%d%d",&N,&M )!=EOF )
 	{
	 	   init();
	 	   work();
  	}
}

下面是匈牙利算法... 简洁啊....


#include<iostream>
using namespace std;

struct node
{
       int link[201];
       int length;
}point[201];

int N,M;
bool visited[201];
int match[201];

bool Match( int pre )
{
     int i;
     for( i=1;i<=point[pre].length;i++ )
     {
          if( !visited[point[pre].link[i]] )   //point[pre].link[i]
          {
              visited[point[pre].link[i]]=true;
              if( match[point[pre].link[i]]==-1 || Match(match[point[pre].link[i]]) )
              {
                  match[point[pre].link[i]]=pre;
                  return true;
              }
          }
     }
     return false;
}

int main()
{
    
    while( scanf("%d %d",&N,&M )!=EOF )
    {
           memset( match,-1,sizeof(match) );
           memset( point,0,sizeof(point) ); 
           int i,j;
           int num;
           for( i=1;i<=N;i++ )
           {
                scanf( "%d",&point[i].length ); 
                for( j=1;j<=point[i].length;j++ )
                     scanf( "%d",&point[i].link[j]);
           }
           int ans=0;
           for( i=1;i<=M;i++ )
           {
                memset( visited,false,sizeof(visited) );
                if( Match(i) ) ans++;
           }
           printf( "%d\n",ans );
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值