HDU 2063 过山车 二分图

Posted on 2011-07-15 22:14  continue_n  阅读(243)  评论(0)    收藏  举报

该题解法思想是:

从第一个女生开始遍历,用女生去选择男生,男生这时还没被选走则马上选走他,接着第二个女生开始选,如果他想要的男生没被选走,当然就选上了,如果该男生已经被选走的话,则开始和前面的选择此男生的女生商量,看她能不能选择别的女生,如果可以的话,就叫该女生选择别的男生,则该男生就属于你了,如果和这个女生商量不成,则换一个男生接着匹配,若没有男生了,则只能守寡了,以此类推……

二分图思想:(匈牙利算法)

二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。

简而言之,就是顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属于这两个互不相交的子集。

(来自百度百科)更多关于二分图资料的请自己查找资料

以下是看了神牛的模版后自己写下的AC代码:

#include <stdio.h>
#include <string.h>
#define MAX 1100
int g[MAX][MAX]; //g[i][j]为真表示 i 可以跟 j 匹配
int xm[MAX],ym[MAX]; // xm[i]=j 表示i已经匹配到j,ym[i]=j 表示i被j配走了
bool pick[MAX]; //pick[i]用来当女生找到的男生已经被匹配走时,让选中该男生的女生再去找别的男生时做标记
int n,m;        //n表示女生的人数,m表示男生的人数
bool Search(int u)     //u表示编号为u的女生,v表示编号为v的男生
{
 int v;
 for( v = 1 ; v <= m ; v++)
 {
  if( g[u][v] && !pick[v] )
  {
   pick[v] = true;  //该标记就是为了在下面这个Search(ym[v])执行时男生不会重复被选到
   if( ym[v] == -1 || Search(ym[v]) )
   {
    xm[u] = v ; ym[v] = u;
    return true;
   }
  }
 }
 return false;
}
int fun()
{
 int u,sum = 0; //sum表示总共可以配对的对数
 memset(xm,-1,sizeof(xm));
 memset(ym,-1,sizeof(ym));
 for( u = 1 ; u <= n ; u++) //u表示变好为u的女生
 {
  if(xm[u] == -1)
  {
   memset(pick,false,sizeof(pick));
   if(Search(u)) sum++;
  }
 }
 return sum;
}
int main()
{
 int k,a,b,i;
 while(scanf("%d",&k),k)
 {
  scanf("%d%d",&n,&m);
  memset(g,0,sizeof(g));
  for( i = 0 ; i < k ; i++)
  {
   scanf("%d%d",&a,&b);
   g[a][b] = 1;
  }
  printf("%d\n",fun());
 }
 return 0;
}

博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3