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;
}

最新文章

  1. Android N做了啥
  2. 【Learning Python】【第三章】表、元组、字典和集合
  3. [原创]cocos2d-x研习录-第三阶 特性之调度器
  4. 【转】Kafka实战-Flume到Kafka
  5. Servlet与JSP的区别
  6. 基于s5pv210的uboot总结
  7. Redhat linux 挂载命令mount
  8. JS脚本语言里的循环
  9. echart图表控件配置入门(二)常用图表数据动态绑定
  10. maven 配置文件详解
  11. 将 Qt 5.6 集成至 VS2015
  12. C语言字符串操作函数集
  13. js所有函数集合
  14. hust1010 kmp
  15. SGD
  16. SPOJ1825:Free tour II
  17. 【Android Studio安装部署系列】十四、Android studio移除工程和删除项目
  18. 当你「ping 一下」的时候,你知道它背后的逻辑吗?
  19. django中文学习资料
  20. pip离线安装软件包

热门文章

  1. 使用RegSetValueEx修改注册表时遇到的问题(转)
  2. 【HASPDOG】hasp_update参数f和i区别
  3. LINUX修改、增加IP的方法,一张网卡绑定多个IP/漂移IP【转】
  4. java系统的优化
  5. Fiddler大师之路系列(一)
  6. redis从入门到放弃 -&gt; 部署方案
  7. Runtime.getRuntime().exec 类 防止阻塞
  8. 数据结构之 栈 (Python 版)
  9. An overview of gradient descent optimization algorithms (更新到Adam)
  10. JSP和Servlet那些事儿系列--HTTPS