题意:有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. IIS 配置好了,为什么网站打开一片空白?

    方法如下: 进入:控制面板 - 卸载程序 - 打开或关闭Windows功能 如果访问任何不存在页面或页面出错时空白: Internet 信息服务 - 万维网服务 - 常见 HTTP 功能 - HTTP ...

  2. C#实现发送邮件

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  3. merge into Oracle里的 saveOrUapdate

    1.初始数据: SQL> select * from a; ID NAME ---------------------- ---------------------- 1 1 2 1 3 1 4 ...

  4. Swift - 21 - 字典实战和UIKit初探

    //: Playground - noun: a place where people can play import UIKit // 数据源 let colors = [ "Air Fo ...

  5. 解决jQuery插件sliderjs, 点击插件分页,导航按钮后不能重新开始.

    jQuery SlidesJS - Can't restart animation after clicking on navigation or pagination <!DOCTYPE ht ...

  6. 使用wireshark抓本机之间的包(转)

    所转地址:http://www.chinadmd.com/file/oc6evrwtzieitexvoupppisr_1.html 在进行通信开发的过程中,我们往往会把本机既作为客户端又作为服务器端来 ...

  7. CMake交叉编译配置

    很多时候,我们在开发的时候是面对嵌入式平台,因此由于资源的限制需要用到相关的交叉编译.即在你host宿主机上要生成target目标机的程序.里面牵扯到相关头文件的切换和编译器的选择以及环境变量的改变等 ...

  8. android异常之emulator-arm.exe已停止工作

    我遇到的这个问题通过降低了AVD的分辨率后解决了,估计是电脑的显卡不行.

  9. Oauth支持的5类 grant_type 及说明

    authorization_code 授权码模式(即先登录获取code,再获取token) password 密码模式(将用户名,密码传过去,直接获取token) client_credentials ...

  10. FLEX 网格布局及响应式处理

    上一篇文章用Flex实现BorderLayout,这一章我们来实现常用的网格布局和响应式处理. 首先我们定义HTML结构,主Box为grid,每项为grid-cell,下面就是我们HTML代码结构. ...