题意:有N个王子M个公主,王子喜欢一些公主,而且只能是王子喜欢的人,他们才可以结婚,现在让他们尽可能多的结婚的前提下找出来每个王子都可以和谁结婚。
分析:先求出来他们的最大匹配,因为给的数据未必是完备匹配,所以需要添加一些点使他们成为完备匹配才能求出来的环是完整的,比如第二组数据:

1 2  

2 1 2
如果不添加虚拟点做成匹配,只会匹配成功一个,这样就找不出来环了,所以需要添加虚拟的王子和公主,虚拟的王子喜欢所有的公主,虚拟的公主被所有的王子喜欢,注意都是王子喜欢公主的,公主没有选择喜欢的权利(确实有点悲哀- -)
*************************************************************************
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std; const int MAXN = ;
const int Base = ;
///base 王子的编号从1开始 公主的编号从base+1开始, 虚拟点的编号从base*2+1开始
int N, M;
bool love[][];
vector< vector <int> >ans;
/***************邻接表*********************/
struct Edge{int v, next;}e[MAXN*MAXN];
int Head[MAXN], cnt; void AddEdge(int u, int v)
{
    e[cnt].v = v;
    e[cnt].next = Head[u];
    Head[u] = cnt++;
}
/**************Tarjan**********************/
int dfn[MAXN], low[MAXN], Index;
int Stack[MAXN], instack[MAXN], top;
int belong[MAXN], bnt; void Tarjan(int i)
{
    int v;     dfn[i] = low[i] = ++Index;
    Stack[++top] = i, instack[i] = true;     for(int j=Head[i]; j!=-; j=e[j].next)
    {
        v = e[j].v;         if( !dfn[v] )
        {
            Tarjan(v);
            low[i] = min(low[i], low[v]);
        }
        else if( instack[v] )
            low[i] = min(low[i], dfn[v]);
    }     if(low[i] == dfn[i])
    {
        ++bnt;
        do
        {
            v = Stack[top--];
            instack[v] = false;
            belong[v] = bnt;
            if(v > Base)
                ans[bnt].push_back(v-Base);
        }
        while(i != v);
    }
}
/***************匈牙利********************/
int Lx[MAXN], Ly[MAXN];
bool used[MAXN]; bool Find(int i)
{
    for(int j=Head[i]; j!=-; j=e[j].next)
    {
        int v = e[j].v;         if( !used[v] )
        {
            used[v] = true;
            if( !Ly[v] || Find(Ly[v]) )
            {
                Ly[v] = i;
                Lx[i] = v;                 return true;
            }
        }
    }     return false;
}
void XYL()///顺便添加虚拟点
{
    int i, j, k, sum=;     for(i=; i<=N; i++)
    {
        memset(used, false, sizeof(used));
        sum += Find(i);
    }     k = Base *  + ;///虚拟点开开始处     for(i=; i<=N; i++)
    {///遍历王子部分,看那个王子没有匹配,为他虚拟一个公主,这个公主所有的王子都喜欢
        if(Lx[i] == false)
        {
            Lx[i] = k;
            Ly[k] = i;             for(j=; j<=N; j++)
                AddEdge(j, k);
            k++;
        }
    }     for(i=Base+; i<=Base+M; i++)
    {///遍历公主部分,看哪个公主没有匹配,为她虚拟一个王子,这个王子喜欢所有的公主
        if(Ly[i] == false)
        {
            Lx[k] = i;
            Ly[i] = k;             for(j=Base+; j<=Base+M; j++)
                AddEdge(k, j);
            k++;
        }
    }     for(i=Base+; i<k; i++)
    {///匹配的点添加反边
        AddEdge( i, Ly[i] );
    }
} /***************初始化********************/
void InIt()
{
    ans.clear();
    ans.resize(MAXN);     memset(love, false, sizeof(love));
    memset(dfn, false, sizeof(dfn));
    memset(Head, -, sizeof(Head));
    memset(Lx, false, sizeof(Lx));
    memset(Ly, false, sizeof(Ly));     cnt = Index = bnt = ;
}
/******************************************/
int main()
{
    int T, t=;     scanf("%d", &T);     while(T--)
    {
        int i, j, v, Len;         scanf("%d%d", &N, &M);
        InIt();         for(i=; i<=N; i++)
        {
            scanf("%d", &Len);             while(Len--)
            {
                scanf("%d", &v);
                AddEdge(i, v+Base);
                love[i][v] = true;
            }
        }         XYL();         for(i=; i<=N; i++)
        {
            if( !dfn[i] )
                Tarjan(i);
        }         printf("Case #%d:\n", t++);
        for(i=; i<=N; i++)
        {
            v = belong[i];
            Len = ans[v].size();             int a[MAXN], k=;             for(j=; j<Len; j++)
            {///王子必须喜欢这个公主才行
                if(love[i][ ans[v][j] ] == true)
                    a[k++] = ans[v][j];
            }             sort(a, a+k);             printf("%d", k);
            for(j=; j<k; j++)
                printf(" %d", a[j]);
            printf("\n");
        }
    }     return ; } 

H - Prince and Princess - HDU 4685(二分匹配+强连通分量)的更多相关文章

  1. Prince and Princess HDU - 4685(匹配 + 强连通)

    Prince and Princess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

  2. hdu 4685 二分匹配+强连通分量

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 题解: 这一题是poj 1904的加强版,poj 1904王子和公主的人数是一样多的,并且给出 ...

  3. poj1904 二分图匹配+强连通分量

    http://poj.org/problem?id=1904 Description Once upon a time there lived a king and he had N sons. An ...

  4. HDU 4685 Prince and Princess (2013多校8 1010题 二分匹配+强连通)

    Prince and Princess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

  5. hdu 4685(匹配+强连通分量)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 思路:想了好久,终于想明白了,懒得写了,直接copy大牛的思路了,写的非常好! 做法是先求一次最 ...

  6. hdu 5093 二分匹配

    /* 题意:给你一些冰岛.公共海域和浮冰,冰岛可以隔开两个公共海域,浮冰无影响 求选尽可能多的选一些公共海域点每行每列仅能选一个. 限制条件:冰山可以隔开这个限制条件.即*#*可以选两个 预处理: * ...

  7. hdu 4169 二分匹配最大独立集 ***

    题意:有水平N张牌,竖直M张牌,同一方向的牌不会相交.水平的和垂直的可能会相交,求最少踢出去几张牌使剩下的牌都不相交. 二分匹配 最小点覆盖=最大匹配. 链接:点我 坐标点作为匹配的端点 #inclu ...

  8. Battle ships HDU - 5093二分匹配

    Battle shipsHDU - 5093 题目大意:n*m的地图,*代表海洋,#代表冰山,o代表浮冰,海洋上可以放置船舰,但是每一行每一列只能有一个船舰(类似象棋的車),除非同行或者同列的船舰中间 ...

  9. hdu 4685 简单匹配+Tarjan算法

    思路:首先看到这题以为能用poj1904的模版直接A掉,WA了几次,然后又TLE了几次.还是想到了正解. 一开始我想的大致方向已经是对的了.先是由王子向每个喜欢的公主建边,再求一次最大匹配,找出匹配后 ...

随机推荐

  1. HDU 5105 Math Problem

    让求  f(x)=|a∗x3+b∗x2+c∗x+d|(L≤x≤R)的最大值 这个题目讨论a和b的值,如果a==0的话,那么这个方程就变成了一个一元二次方程,直接找端点和对称轴(如果对称轴在给定的区间内 ...

  2. HDU 3533 Escape(bfs)

    Escape Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  3. C#与.Net Framework的各种版本和联系

    C#是微软公司发布的一种面向对象的.运行于.NET Framework之上的高级程序设计语言.并定于在微软职业开发者论坛(PDC)上登台亮相.C#是微软公司研究员Anders Hejlsberg的最新 ...

  4. JavaScript实现弹框

    提起JS弹框,我首先想到的是Alert,然后想到的还是Alert,最后我竟然就只知道Alert.然后面试就死在这个Alert上了.恼火. 根据网上各位大神的总结,我整理了一下,也顺便学习了一下. 一. ...

  5. iOS学习笔记(十四)——打电话、发短信

    电话.短信是手机的基础功能,iOS中提供了接口,让我们调用.这篇文章简单的介绍一下iOS的打电话.发短信在程序中怎么调用. 1.打电话 [[UIApplication sharedApplicatio ...

  6. UITouch触摸事件

    UITouch触摸事件 主要为三个方法 1.-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{2.3. UITouch * ...

  7. 虾米loop 摇头代码

    .head{ position: absolute; -webkit-animation: shake 1s infinite; -webkit-transform-origin: center bo ...

  8. 《JavaScript dom 编程艺术》 placeholder占位符IE8兼容办法。

    在<JavaScript dom 编程艺术>第11章学来的. 相对于用JavaScript替换文本框的提示语句 <!DOCTYPE html> <html lang=&q ...

  9. 关于highcharts(功能强大、开源、美观、图表丰富、兼容绝大多数浏览器的纯js图表库)

    官网http://www.hcharts.cn/ 引入下列文件 <script type="text/javascript" src="http://cdn.hch ...

  10. 15 3Sum(寻找三个数之和为指定数的集合Medium)

    题目意思:给一个乱序数组,在里面寻找三个数之和为0的所有情况,这些情况不能重复,增序排列 思路:前面2sum,我用的是map,自然那道题map比双指针效率高,这道题需要先排序,再给三个指针,i.j.k ...