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

  • 相关阅读:
    20150826运算符,if语句
    20150825数据类型以及数据转换
    !!!SQL sever 函数表达
    SQL
    !!!遍历数组之多维数组!
    数组应用之————二分法查找
    数组-冒泡排列
    Homework!---判断多久过生日
    C#——语句!
    C#——语言基础 之 运算符!
  • 原文地址:https://www.cnblogs.com/csnd/p/12063145.html
Copyright © 2020-2023  润新知