Prince and Princess

题目连接:

http://acm.hdu.edu.cn/showproblem.php?pid=4685

Description

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

Hint

题意

有n个王子,m个公主

每个王子喜欢ki个公主,现在把每个王子喜欢的公主都给了出来

国王叫大臣制作一张表,输出每个王子和这个公主结婚之后,满足不会影响别人结婚的条件

如果这个王子和这个公主结婚之后,依旧是一个完备匹配的话,就输出

题解:

和poj 1904不一样的是,这道题并没有给出完备匹配,而且男女人数不相等

这一点的话,我们可以先求一个二分图的最大匹配之后,假设匹配数是cnt

那么把左右两边的点都补充为n+m-cnt个点,然后再跑二分图

跑完之后就可以得到完备匹配了,然后就和1904做法一样了。

空间注意开大一点,不然会迷之wa……

不过我的做法不一样,我后面跑tarjan的时候,是让公主之间连边,让这个王子匹配的公主,和他喜欢的公主连边

然后跑的tarjan

代码

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 3e3+6;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,k,dfn[maxn],low[maxn],_clock=0,sta[maxn],top;
bool in_sta[maxn];
int changed[maxn],scc,num[maxn],vis[maxn],Left[maxn],Rht[maxn],mp[1005][1005];
vector<int> E[maxn],G[maxn];
vector<int>lft[maxn];
vector<int> ans;
void init()
{
memset(Rht,0,sizeof(Rht));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(sta,0,sizeof(sta));
memset(in_sta,0,sizeof(in_sta));
memset(changed,0,sizeof(changed));
memset(num,0,sizeof(num));
memset(vis,0,sizeof(vis));
memset(mp,0,sizeof(mp));
memset(Left,-1,sizeof(Left));
for(int i=0;i<maxn;i++)E[i].clear(),G[i].clear();
for(int i=0;i<maxn;i++)lft[i].clear();
scc=0;top=0;_clock=0;
}
void tarjan(int x)
{
dfn[x]=low[x]=++_clock;
sta[++top]=x;
in_sta[x]=1;
for(int i=0;i<E[x].size();i++)
{
int v = E[x][i];
if(!dfn[v])
tarjan(v),low[x]=min(low[x],low[v]);
else if(in_sta[v])
low[x]=min(low[x],dfn[v]);
}
if(dfn[x]==low[x])
{
int temp;
++scc;
do{
temp = sta[top--];
in_sta[temp]=0;
changed[temp]=scc;
++num[scc];
}while(temp!=x);
}
}
void add(int x,int y)
{
lft[x].push_back(y);
}
int dfs2(int x){
for(int i=0;i<lft[x].size();i++){
int it=lft[x][i];
if(Left[it] == -1){
Left[it] = x;
Rht[x]=it;
return 1;
}
if(vis[it]) continue;
vis[it] = 1;
if(dfs2(Left[it])){
Left[it] = x;
Rht[x]=it;
return 1;
}
}
return 0;
}
void solve(int cas)
{
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
int x=read();
for(int j=0;j<x;j++)
{
int y=read();
add(i,n+y);
G[i].push_back(y);
}
}
int cnt=0;
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
cnt+=dfs2(i);
}
for(int i=0;i<maxn;i++)lft[i].clear();
memset(Left,-1,sizeof(Left));
for(int i=1;i<=n;i++)
{
for(int j=0;j<G[i].size();j++)
{
mp[i][G[i][j]]=1;
add(i,n+m-cnt+G[i][j]);
}
}
for(int i=n+1;i<=n+m-cnt;i++)
{
for(int j=1;j<=n+m-cnt;j++)
{
mp[i][j]=1;
add(i,n+m-cnt+j);
}
}
for(int i=1;i<=n;i++)
{
for(int j=m+1;j<=n+m-cnt;j++)
{
mp[i][j]=1;
add(i,n+m-cnt+j);
}
}
for(int i=1;i<=n+m-cnt;i++)
{
memset(vis,0,sizeof(vis));
dfs2(i);
}
for(int i=1;i<=n+m-cnt;i++)
{
for(int j=1;j<=n+m-cnt;j++)
{
if(Rht[i]-n-m+cnt!=j&&mp[i][j])
E[Rht[i]-n-m+cnt].push_back(j);
}
}
for(int i=1;i<=(n+m-cnt);i++)
if(!dfn[i])tarjan(i);
printf("Case #%d:\n",cas);
for(int i=1;i<=n;i++)
{
ans.clear();
for(int j=1;j<=m;j++)
{
if(mp[i][j]&&changed[Rht[i]-n-m+cnt]==changed[j])
ans.push_back(j);
}
printf("%d",ans.size());
for(int j=0;j<ans.size();j++)
printf(" %d",ans[j]);
printf("\n");
}
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
solve(i);
return 0;
}

HDU 4685 Prince and Princess 二分图匹配+tarjan的更多相关文章

  1. 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 ...

  2. HDU 4685 Prince and Princess(二分图+强连通分量)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:给出n个王子和m个公主.每个王子有一些自己喜欢的公主可以匹配.设最大匹配为M.那么对于每个 ...

  3. HDU 4685 Prince and Princess(二分匹配+强联通分量)

    题意:婚配问题,但是题目并不要求输出最大匹配值,而是让我们输出,一个王子可以与哪些王妃婚配而不影响最大匹配值. 解决办法:先求一次最大匹配,如果有两个已经匹配的王妃,喜欢她们两个的有两个或者以上相同的 ...

  4. hdu 4685 Prince and Princess(匈牙利算法 连通分量)

    看了别人的题解.须要用到匈牙利算法的强连通算法 #include<cstdio> #include<algorithm> #include<vector> #pra ...

  5. HDU 4685 Prince and Princess

    强连通分量,看大神的题解才会写的.... http://www.cnblogs.com/kuangbin/p/3261157.html 数据量有点大,第一次Submit 2995ms过的,时限3000 ...

  6. HDU4685:Prince and Princess(二分图匹配+tarjan)

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

  7. hdu 3829 Cat VS Dog 二分图匹配 最大点独立集

    Cat VS Dog Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others) Prob ...

  8. HDU 2236 无题II(二分图匹配+二分)

    HDU 2236 无题II 题目链接 思路:行列仅仅能一个,想到二分图,然后二分区间长度,枚举下限.就能求出哪些边是能用的,然后建图跑二分图,假设最大匹配等于n就是符合的 代码: #include & ...

  9. TTTTTTTTTTTTTTTT hdu 5727 Necklace 阴阳珠 二分图匹配+暴力全排列

    Necklace Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Su ...

随机推荐

  1. PCI学习之总线原理01

    -----------以下资料由网络资料整理而成-------- PCI即Peripheral Component Interconnect,中文的意思是“外围器件互联”. PCI总线支持32位和64 ...

  2. Linux USB驱动学习总结(三)---- USB鼠标的加载、初始化和通信过程

    1.usbmouse的定义:usb鼠标既包含usb设备(usb_device)的属性也包含input输入设备(input_dev)的属性 struct usb_mouse { ];///USB鼠标设备 ...

  3. linux系统编程之信号:信号发送函数sigqueue和信号安装函数sigaction

    信号发送函数sigqueue和信号安装函数sigaction sigaction函数用于改变进程接收到特定信号后的行为. sigqueue()是比较新的发送信号系统调用,主要是针对实时信号提出的(当然 ...

  4. 读书笔记 effective c++ Item 19 像设计类型(type)一样设计类

    1. 你需要重视类的设计 c++同其他面向对象编程语言一样,定义了一个新的类就相当于定义了一个新的类型(type),因此作为一个c++开发人员,大量时间会被花费在扩张你的类型系统上面.这意味着你不仅仅 ...

  5. Pytorch多进程最佳实践

    预备知识 模型并行( model parallelism ):即把模型拆分放到不同的设备进行训练,分布式系统中的不同机器(GPU/CPU等)负责网络模型的不同部分 —— 例如,神经网络模型的不同网络层 ...

  6. 24 The Go image package go图片包:图片包的基本原理

    The Go image package  go图片包:图片包的基本原理 21 September 2011 Introduction The image and image/color packag ...

  7. Java数据类型以及变量的定义

    1130136248   Java的基本数据类型 变量就是申请内存来存储值.也就是说,当创建变量的时候,需要在内存中申请空间. 内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类 ...

  8. 【web开发】web前端开发常用技术总结归纳

    技术选型规范规范 • Vue版本:2.x • 前端路由:vue-route • 异步请求:Axios • 全局状态管理:VueX • css预处理器:sass/less • h5项目移动端适配规则:使 ...

  9. python图片处理和matlab图片处理的区别

    作者:波布兰链接:https://www.zhihu.com/question/28218420/answer/39904627来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  10. 进程同步——哲学家进餐问题Java实现

    哲学家就餐问题是1965年由Dijkstra提出的一种线程同步的问题. 问题描述:一圆桌前坐着5位哲学家,两个人中间有一只筷子,桌子中央有面条.哲学家思考问题,当饿了的时候拿起左右两只筷子吃饭,必须拿 ...