zoukankan      html  css  js  c++  java
  • HDU 4685 Prince and Princess

    Prince and Princess

    Time Limit: 3000ms
    Memory Limit: 32768KB
    This problem will be judged on HDU. Original ID: 4685
    64-bit integer IO format: %I64d      Java class name: Main
     
    There are n princes and m princesses. Princess can marry any prince. But prince can only marry the princess they DO love.
    For all princes,give all the princesses that they love. So, there is a maximum number of pairs of prince and princess that can marry.
    Now for each prince, your task is to output all the princesses he can marry. Of course if a prince wants to marry one of those princesses,the maximum number of marriage pairs of the rest princes and princesses cannot change.
     

    Input

    The first line of the input contains an integer T(T<=25) which means the number of test cases.
    For each test case, the first line contains two integers n and m (1<=n,m<=500), means the number of prince and princess.
    Then n lines for each prince contain the list of the princess he loves. Each line starts with a integer ki(0<=ki<=m), and then ki different integers, ranging from 1 to m denoting the princesses.
     

    Output

    For each test case, first output "Case #x:" in a line, where x indicates the case number between 1 and T.
    Then output n lines. For each prince, first print li, the number of different princess he can marry so that the rest princes and princesses can still get the maximum marriage number.
    After that print li different integers denoting those princesses,in ascending order.
     

    Sample Input

    2
    4 4
    2 1 2
    2 1 2
    2 2 3
    2 3 4
    1 2
    2 1 2

    Sample Output

    Case #1:
    2 1 2
    2 1 2
    1 3
    1 4
    Case #2:
    2 1 2

    Source

     
    解题:完备匹配+强连通。至于求强连通,有两种建图方式。
     
    方式一:把王子也作为图的顶点,建图,匹配边是从公主指向王子,非匹配边,王子指向公主,当然必须是喜欢的。
     
    方式二:直接建立只包含公主的图进行求强连通,然后看与该王子已匹配的公主所在的强联通分量中,还有哪些是王子喜欢。喜欢的即可以互换?人妻互换???????好邪恶的样子!!!!!一个圈,转一圈,还是自己喜欢的另一个她。。。。。
     
    我采用的是第二种方式建图的。。。
     
    不过,有个地方要注意下,n与m不想等,所以,要创建虚拟女友跟虚拟男友了。。。。。不然怎么完备匹配。。。。
     
    建立虚拟女友,每个王子都喜欢的
    建立虚拟男友,喜欢每个公主。。。
     
    他们之间的关系。。。。很复杂。。。。
     
    此图貌似求最大匹配很费时,下次改成HK玩玩,啊哈,interesting啊!!!!!
     
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 #include <climits>
      7 #include <vector>
      8 #include <queue>
      9 #include <cstdlib>
     10 #include <string>
     11 #include <set>
     12 #include <stack>
     13 #define LL long long
     14 #define pii pair<int,int>
     15 #define INF 0x3f3f3f3f
     16 using namespace std;
     17 const int maxn = 50000;
     18 struct arc {
     19     int to,next;
     20     arc(int x = 0,int y = -1) {
     21         to = x;
     22         next = y;
     23     }
     24 };
     25 arc e[500000];
     26 int head[maxn],dfn[maxn],low[maxn],belong[maxn];
     27 int tot,nx,ny,top,scc,idx,lx[maxn],ly[maxn],mystack[maxn];
     28 bool mp[1000][1000],instack[maxn],vis[maxn];
     29 void add(int u,int v) {
     30     e[tot] = arc(v,head[u]);
     31     head[u] = tot++;
     32 }
     33 bool dfs(int u) {
     34     for(int i = 1; i <= ny; ++i) {
     35         if(mp[u][i]&&!vis[i]) {
     36             vis[i] = true;
     37             if(ly[i] == -1 || dfs(ly[i])) {
     38                 ly[i] = u;
     39                 lx[u] = i;
     40                 return true;
     41             }
     42         }
     43     }
     44     return false;
     45 }
     46 int hungry() {
     47     memset(lx,-1,sizeof(lx));
     48     memset(ly,-1,sizeof(ly));
     49     int ans = 0;
     50     for(int i = 1; i <= nx; ++i) {
     51         memset(vis,false,sizeof(vis));
     52         ans += dfs(i);
     53     }
     54     return ans;
     55 }
     56 void tarjan(int u) {
     57     dfn[u] = low[u] = ++idx;
     58     instack[u] = true;
     59     mystack[top++] = u;
     60     for(int i = head[u]; ~i; i = e[i].next) {
     61         if(!dfn[e[i].to]) {
     62             tarjan(e[i].to);
     63             low[u] = min(low[u],low[e[i].to]);
     64         } else if(instack[e[i].to]) low[u] = min(low[u],dfn[e[i].to]);
     65     }
     66     if(dfn[u] == low[u]) {
     67         int v;
     68         scc++;
     69         do {
     70             v = mystack[--top];
     71             instack[v] = false;
     72             belong[v] = scc;
     73         } while(v != u);
     74     }
     75 }
     76 void init() {
     77     for(int i = 0; i < maxn; ++i) {
     78         dfn[i] = low[i] = belong[i] = 0;
     79         instack[i] = false;
     80         head[i] = -1;
     81     }
     82     tot = scc = idx = top = 0;
     83     memset(mp,false,sizeof(mp));
     84 }
     85 int main() {
     86     int T,cs = 1,n,m,k,u,v;
     87     scanf("%d",&T);
     88     while(T--) {
     89         scanf("%d %d",&n,&m);
     90         nx = n;
     91         ny = m;
     92         init();
     93         for(int i = 1; i <= n; ++i) {
     94             scanf("%d",&k);
     95             while(k--) {
     96                 scanf("%d",&v);
     97                 mp[i][v] = true;
     98             }
     99         }
    100         nx = ny = n + m - hungry();
    101         for(int i = n+1; i <= nx; ++i)
    102             for(int j = 1; j <= ny; ++j)
    103                 mp[i][j] = true;//建立虚拟王子
    104         for(int i = m+1; i <= ny; ++i)
    105             for(int j = 1; j <= nx; ++j)
    106                 mp[j][i] = true;//建立虚拟公主
    107         hungry();
    108         for(int i = 1; i <= nx; ++i) {
    109             for(int j = 1; j <= ny; ++j)
    110                 if(mp[i][j] && lx[i] != j)  add(lx[i],j);
    111         }
    112         for(int i = 1; i <= nx; ++i)
    113             if(!dfn[i]) tarjan(i);
    114         printf("Case #%d:
    ",cs++);
    115         vector<int>ans;
    116         for(int i = 1; i <= n; ++i) {
    117             ans.clear();
    118             for(int j = m; j >= 0; --j)
    119                 if(mp[i][j]&& belong[lx[i]] == belong[j]) ans.push_back(j);
    120             printf("%d",ans.size());
    121             for(int j = ans.size()-1; j >= 0; --j)
    122                 printf(" %d",ans[j]);
    123             putchar('
    ');
    124         }
    125     }
    126     return 0;
    127 }
    View Code
  • 相关阅读:
    bzoj 1911: [Apio2010]特别行动队
    bzoj 1096: [ZJOI2007]仓库建设
    bzoj 3522: [Poi2014]Hotel
    bzoj 3572: [Hnoi2014]世界树
    bzoj 1177: [Apio2009]Oil
    bzoj 1912: [Apio2010]patrol 巡逻
    bzoj 3573: [Hnoi2014]米特运输
    bzoj 3997: [TJOI2015]组合数学
    cf 506 A. Mr. Kitayuta, the Treasure Hunter
    cf 500 D. New Year Santa Network
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4090782.html
Copyright © 2011-2022 走看看