求最小点覆盖集,最小点覆盖集=最大匹配集,继续匈牙利算法解决
这里注意,输入的是根树
一开始想先把根树转回二部图,发现比较麻烦
最后直接把根树看成无向图来解决,即把边看成无向边,建立邻接表时一直两个
顶点都插入,最后求得的匹配数除二就ok了
不过时间用了太多了,有空再想优化吧
543+ms代码
#include<iostream>                                                                          
typedef struct link
{
 int id;
 link *next;
}link;

int flag[1501];
link *head[1501]; 
link *last[1501];
int result[1501];

bool find(int x)
{
 link *p=head[x];
 while(p!=NULL)
 {
  if(!flag[p->id])
  {
   flag[p->id]=1;
   if((result[p->id]<0)||find(result[p->id]))
   {
    result[p->id]=x;
    return true;
   }
  }
  p=p->next;
 }
 return false;
}

int main()
{
 int n,x,y,m,i,j,ans;
 link *p;
 while(scanf("%d",&n)!=EOF)
 {
  for(i=0;i<n;i++)
  {
   head[i]=NULL;
   result[i]=-1;
  }
  for(i=0;i<n;i++)
  {

   scanf("%d:(%d)",&x,&m);
   for(j=0;j<m;j++)
   {
    scanf("%d",&y);
       p=(link*)malloc(sizeof(link));
    p->id=y;
    p->next=NULL;
    if(head[x]==NULL)
    {
     head[x]=p;
     last[x]=head[x];
    }
    else
    {
     last[x]->next=p;
     last[x]=last[x]->next;
    }
    p=(link*)malloc(sizeof(link));
    p->id=x;
    p->next=NULL;
    if(head[y]==NULL)
    {
     head[y]=p;
     last[y]=head[y];
    }
    else
    {
     last[y]->next=p;
     last[y]=last[y]->next;
    }
   }
  }

  ans=0;
  for(i=0;i<n;i++)
  {
   memset(flag,0,sizeof(flag));
   if(find(i)) ans++;
  }
  printf("%d\n",ans/2);
 }
 return 0;
}