zoukankan      html  css  js  c++  java
  • POJ1904 强联通(最大匹配可能性)

    题意:
          有n个王子,n个公主,然后给你每个王子喜欢的公主,最后问你在不影响最大匹配的前提下,每个王子可以匹配那些公主。

    思路:

          是hdu4685的减弱版,之前研究过hdu4685所以这个题目直接水过了,对于这个题目,我们把王子和他喜欢的公主之间建连边,建立一个二分图,然后对于题目给的已经匹配好了的(有的题目没给,直接就自己跑一边二分匹配自己找),之间建立反边,就是建立公主到王子的边,然后一遍强联通,如果同意个分量里的男女可以匹配。这样记录每一个然后sort一下就行了。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<stack>
    
    #define N_node 5000
    #define N_edge 1000000
    
    using namespace std;
    
    typedef struct
    {
       int to ,next;
    }STAR;
    
    STAR E1[N_edge] ,E2[N_edge];
    int list1[N_node] ,list2[N_node] ,tot;
    int Belong[N_node] ,cont;
    int mark[N_node];
    int ans[N_node];
    stack<int>st;
    
    void add(int a ,int b)
    {
        E1[++tot].to = b;
        E1[tot].next = list1[a];
        list1[a] = tot;
        E2[tot].to = a;
        E2[tot].next = list2[b];
        list2[b] = tot;
    }
    
    void DFS1(int s)
    {
        mark[s] = 1;
        for(int k = list1[s] ;k ;k = E1[k].next)
        {
           int to = E1[k].to;
           if(!mark[to]) DFS1(to);
        }
        st.push(s);
    }
    
    void DFS2(int s)
    {
       
       mark[s] = 1;
       Belong[s] = cont;
       for(int k = list2[s] ;k ;k = E2[k].next)
       {
           int to = E2[k].to;
           if(!mark[to]) DFS2(to);
       }
    }
    
    int main ()
    {
        int n ,i ,j ,a ,nn;
        while(~scanf("%d" ,&n))
        {
           memset(list1 ,0 ,sizeof(list1));
           memset(list2 ,0 ,sizeof(list2));
           tot = 1;
           for(i = 1 ;i <= n ;i ++)
           {
               scanf("%d" ,&nn);
               for(j = 1 ;j <= nn ;j ++)
               {
                   scanf("%d" ,&a);
                   add(i ,a + n);
               }
           }
           
           for(i = 1 ;i <= n ;i ++)
           {
              scanf("%d" ,&a);
              add(a + n ,i);
           }
          
           memset(mark ,0 ,sizeof(mark));
           while(!st.empty()) st.pop();
           for(i = 1 ;i <= n + n ;i ++)
           {
               if(!mark[i]) DFS1(i);
           }
           memset(mark ,0 ,sizeof(mark));
           cont = 0;
           while(!st.empty())
           {
               int to = st.top();
               st.pop(); 
               if(!mark[to])
               {
                  cont ++;
                  DFS2(to);
               }
           }      
           for(i = 1 ;i <= n ;i ++)
           {
               int tt = 0;
               for(int k = list1[i] ;k ;k = E1[k].next)
               {
                  int to = E1[k].to;
                  if(Belong[i] == Belong[to])
                  ans[++tt] = to - n;
               }
               sort(ans + 1 ,ans + tt + 1);
               printf("%d" ,tt);
               for(j = 1 ;j <= tt ;j ++)
               printf(" %d" ,ans[j]);
               puts("");
           }
        }
        return 0;
    }
               
               
               

  • 相关阅读:
    synchronized 关键字
    synchronized 关键字
    Linux IPC之共享内存
    链表的插入、删除
    链式队列的实现
    链栈的实现
    双色、三色排序问题
    memmove、memcpy、strcpy、memset的实现
    字符串中去掉多余的空格
    华为机试:从一个数组中选取不同的数(均小于10)组成一个最大的三位数
  • 原文地址:https://www.cnblogs.com/csnd/p/12063046.html
Copyright © 2011-2022 走看看