hdu4685 最大匹配可能性

题意:
      给你n个王子和m个公主,每个王子可以和自己喜欢的公主结婚,问你在不影响最大匹配的前提下每个王子都可以去哪些公主.


思路:

      所有王子向他喜欢的公主连一条边,然后匹配一遍,之后再每个匹配的公主连一条指向娶她的王子一条边,然后对于那些光棍王子和单身公主们,其实他们可以和任意他们喜欢的人匹配,因为可以让自己幸福,然后拆散一对别人已经匹配好的,虽然不道德,但是仍然满足总的最大匹配数不变,所以对于每一个光棍男我们就给他虚拟出一个女朋友,所有人都喜欢这个女的,但是这个女的只喜欢并且和该光棍男匹配,女的也类似这样弄,最后每个人都有匹配的对象了,此时我们只要跑一遍强连通,同一个强连通分量里的男和女可以随意匹配..


#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stack>
#include<map>

#define N_node 5000
#define N_edge 600000

using namespace std;

typedef struct
{
   int to ,next;
}STAR;

STAR E[N_edge] ,_E[N_edge] ,__E[N_edge];
map<int ,map<int ,int> >mk_map;
int list[N_node] ,_list[N_node] ,tot , _tot;
int Belong[N_node] ,cout;
int mk_dfs[N_node] ,mk_gx[N_node];
int mk_M[550] ,mk_G[550];
stack<int>st; 


void add(int a, int b)
{
   E[++tot].to = b;
   E[tot].next = list[a];
   list[a] = tot;
   
   _E[++_tot].to = a;
   _E[_tot].next = _list[b];
   _list[b] = _tot;
}


int DFS_XYL(int s)
{
   for(int k = list[s] ;k ;k = E[k].next)
   {
      int to = E[k].to;
      if(mk_dfs[to]) continue;
      mk_dfs[to] = 1;
      if(mk_gx[to] == -1 || DFS_XYL(mk_gx[to]))
      {
         mk_gx[to] = s;
         return 1;
      }
   }
   return 0;
}

void DFS_1(int s)
{
   mk_dfs[s] = 1;
   for(int k = list[s] ;k ;k = E[k].next)
   {
      int to = E[k].to;
      if(mk_dfs[to]) continue;
      DFS_1(to);
   }
   st.push(s);
}

void DFS_2(int s)
{
   mk_dfs[s] = 1;
   Belong[s] = cout;
   for(int k = _list[s] ;k ;k = _E[k].next)
   {
      int to = _E[k].to;
      if(mk_dfs[to]) continue;
      DFS_2(to);
   }
}

void solve(int cas)
{
   int n ,m ,i ,j;
   int a ,b ,c;
   scanf("%d %d" ,&n ,&m);
   memset(list ,0 ,sizeof(list));
   memset(_list ,0 ,sizeof(_list));
   tot = _tot = 1;
   mk_map.clear();
   for(i = 1 ;i <= n ;i ++)
   {
      scanf("%d" ,&c);
      while(c--)
      {
         scanf("%d" ,&a);
         add(i ,a + n);
         mk_map[i][a] = 1;
      }
   }
   memset(mk_gx ,255 ,sizeof(mk_gx));
   int sum = 0;
   for(i = 1 ;i <= n ;i ++)
   {
      memset(mk_dfs ,0 ,sizeof(mk_dfs));
      mk_M[i] =  DFS_XYL(i);
      sum += mk_M[i];
   }
   for(i = 1 ;i <= m ;i ++)
   {
      if(mk_gx[i + n] == -1) mk_G[i] = 0;
      else
      {
         mk_G[i] = 1;
         add(i + n ,mk_gx[i + n]);
      }
   }
   int nowid = n + m;
   for(i = 1 ;i <= n ;i ++)
   {
      if(mk_M[i]) continue;
      nowid ++;
      for(j = 1 ;j <= n ;j ++)
      add(j ,nowid);
      add(nowid ,i);
   }
   for(i = 1 ;i <= m ;i ++)
   {
      if(mk_G[i]) continue;
      nowid ++;
      for(j = 1 ;j <= m ;j ++)
      add(nowid ,j + n);
      add(i + n ,nowid);
   }
    memset(mk_dfs ,0 ,sizeof(mk_dfs));
   while(!st.empty()) st.pop();
   for(i = 1 ;i <= nowid ;i ++)
   {
      if(mk_dfs[i]) continue;
      DFS_1(i);
   }
    
   cout = 0;
   memset(mk_dfs ,0 ,sizeof(mk_dfs));
   while(!st.empty())
   {
      int to = st.top();
      st.pop();
      if(mk_dfs[to]) continue;
      cout ++;
      DFS_2(to);
   }      
   printf("Case #%d:
" ,cas);
   int tmp[550];
   for(i = 1 ;i <= n ;i ++)
   {
      int tt = 0;
      for(int k = list[i] ;k ;k = E[k].next)
      {
         int to = E[k].to;
         if(mk_map[i][to - n] && Belong[i] == Belong[to])
         tmp[++tt] = to - n;
      }
      sort(tmp + 1 ,tmp + tt + 1);      
      printf("%d" ,tt);
      for(int k = 1 ;k <= tt ;k ++)
      printf(" %d" ,tmp[k]);
      printf("
");
   }
}


int main ()
{
   int cas = 1 ,t;
   scanf("%d" ,&t);
   while(t--)
   {
      solve(cas++);
   }
   return 0;
}
   
      

原文地址:https://www.cnblogs.com/csnd/p/12063145.html