题意:

有n个王子和m个公主,每个王子都会喜欢若干个公主,也就是王子只跟自己喜欢的公主结婚,公主就比较悲惨, 跟谁结婚都行。然后输出王子可能的结婚对象,必须保证王子与任意这些对象中的一个结婚,都不会影响到剩余的王子的配对数,也就是不能让剩余的王子中突然有一个人没婚可结了。

思路:

对每个没有匹配的公主,建一个虚拟的王子,让他们变成匹配,然后由这个虚拟王子向每个公主建边。对每个没有匹配的王子,建一个虚拟的公主,让他们变成匹配,然后每个王子向这个虚拟公主建边。求一个Tarjan,判断是否为1个强连通分量即可。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define maxn 2005 using namespace std; int dfn[maxn],low[maxn],vi[maxn],Stack[maxn],head[maxn],id[maxn],n,e,lab,num,top,ans[maxn];
int graphic[][],m,match[maxn],cho[maxn],mm; struct Edge{
int u,v,next;
}edge[]; vector<int> q[maxn],girl[maxn]; void init()
{
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(vi,,sizeof(vi));
memset(head,-,sizeof(head));
memset(id,,sizeof(id));
memset(graphic,,sizeof(graphic));
memset(cho,,sizeof(cho));
memset(match,-,sizeof(match));
memset(ans,,sizeof(ans));
for(int i=;i<maxn;i++)
q[i].clear(),girl[i].clear();
e=lab=num=top=mm=;
} void add(int u,int v)
{
edge[e].u=u,edge[e].v=v,edge[e].next=head[u],head[u]=e++;
} int dfs(int u)//匈牙利算法
{
int i;
for(i=;i<=m;i++)
{
if(!vi[i]&&graphic[u][i])
{
vi[i]=;
if(match[i]==-||dfs(match[i]))
{
match[i]=u;
return ;
}
}
}
return ;
} int Tarjan(int u)
{
dfn[u]=low[u]=++lab;
vi[u]=;
Stack[top++]=u;
int i,v;
for(i=head[u];i!=-;i=edge[i].next)
{
v=edge[i].v;
if(!dfn[v])
{
Tarjan(v);
low[u]=min(low[u],low[v]);
}
if(vi[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
++num;
do{
i=Stack[--top];
vi[i]=;
id[i]=num;
}while(i!=u);
}
return ;
} void solve()
{
int i,j;
for(i=;i<=n+m+mm;i++)
if(!dfn[i])
Tarjan(i);
for(i=n+;i<=n+m;i++)
{
q[id[i]].push_back(i-n);
}
int cnt=;
for(i=;i<=n;i++)
{
int size=q[id[i]].size();
cnt=;
for(j=;j<size;j++)
{
if(graphic[i][q[id[i]][j]])
ans[cnt++]=q[id[i]][j];
}
printf("%d",cnt);
for(j=;j<cnt;j++)
printf(" %d",ans[j]);
printf("\n");
}
} int main()
{
int a,b,i,j,t,Case=;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d%d",&n,&m);
for(i=;i<=n;i++)
{
scanf("%d",&a);
while(a--)
{
scanf("%d",&b);
add(i,b+n);
graphic[i][b]=;
}
}
int num=;
memset(match,-,sizeof(match));
for(i=;i<=n;i++)
{
memset(vi,,sizeof(vi));
if(dfs(i))
num++;
}
mm=;
for(i=;i<=m;i++)
{
if(match[i]==-)
{
mm++;
add(n+m+mm,i+n);
add(i+n,n+m+mm);
for(j=;j<=m;j++)
add(n+m+mm,j+n);
}
else
{
cho[match[i]]=;
}
add(i+n,match[i]);
}
for(i=;i<=n;i++)
{
if(cho[i]==)
{
mm++;
add(i,n+m+mm);
add(n+m+mm,i);
for(j=;j<=n;j++)
add(j,n+m+mm);
}
}
memset(vi,,sizeof(vi));
printf("Case #%d:\n",++Case);
solve();
}
return ;
}

HDU4685 Prince and Princess【强连通】的更多相关文章

  1. 强连通+二分匹配(hdu4685 Prince and Princess)

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

  2. HDU4685 Prince and Princess 完美搭配+良好的沟通

    意甲冠军:今天,有n王子,m公主.现在给他们配对,与王子会嫁给一个男人,他喜欢.公主无法做出选择. 这标题去咬硬,还有一类似的题目poj1904.那个题目也是给王子与公主配对,但那个是王子公主各n个, ...

  3. HDU4865 Prince and Princess 强连通分量+二分图判定

    这个题就是建图费点劲,别的和我上一篇博客一样 然后,参考思路请戳这里http://www.cnblogs.com/wally/archive/2013/09/12/3317883.html 补充:这个 ...

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

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

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

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

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

  7. 10635 - Prince and Princess

    Problem D Prince and Princess Input: Standard Input Output: Standard Output Time Limit: 3 Seconds In ...

  8. UVa10653.Prince and Princess

    题目连接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  9. uva 10635 - Prince and Princess(LCS)

    题目连接:10635 - Prince and Princess 题目大意:给出n, m, k,求两个长度分别为m + 1 和 k + 1且由1~n * n组成的序列的最长公共子序列长的. 解题思路: ...

随机推荐

  1. Django model 中的字段解释

    Django 通过 models 实现数据库的创建.修改.删除等操作,本文为模型中一般常用的类型的清单,便于查询和使用: AutoField:一个自动递增的整型字段,添加记录时它会自动增长.你通常不需 ...

  2. Codeforces ECR47F Dominant Indices(线段树合并)

    一个比较显然的做法:对每棵子树用线段树维护其中的深度,线段树合并即可. 本来想用这个题学一下dsu on tree,结果还是弃疗了. #include<iostream> #include ...

  3. 自学Linux Shell17.1-正则表达式

    点击返回 自学Linux命令行与Shell脚本之路 17.1-正则表达式 1. 正则表达式概念 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“ ...

  4. luogu1600 [NOIp2016]天天爱跑步 (tarjanLca+dfs)

    经过部分分的提示,我们可以把一条路径切成s到lca 和lca到t的链 这样就分为向上的链和向下的链,我们分开考虑: 向上:如果某一个链i可以对点x产生贡献,那么有deep[x]+w[x]=deep[S ...

  5. ->2018.06 计划

    2018.4.14->2018.06计划 力求掌握以下几种算法: 树链剖分 网络流 主席树 splay 莫队

  6. 【bzoj3039】玉蟾宫 悬线法

    悬线法是一种更优秀的枚举方式,保证了枚举悬线的集合包含了极大子矩形所在的集合,而且由最大子矩形一定是极大子矩形的定理可知,这种枚举方式可以求出最大子矩形. 具体做法是维护矩形中每个元素对应最近的左边和 ...

  7. Java:判断当前操作系统界面采用的主题是windows经典样式还是xp样式

    想起两三年前,发现写Java界面的时候,如果将当前界面的layout设为null,由于windows的不同主题界面下,标题栏的高度不一致,导致当前界面表现也不一致. 当时就想找到一个办法先判断当前用户 ...

  8. idea中的language level 介绍

    language level 介绍 其他 IDE 没有看到类似 language level 的设置,所以这个功能应该算是 IntelliJ IDEA 特有的,可是 IntelliJ IDEA 官网也 ...

  9. MYCAT全局序列

    1.本地文件方式 sequnceHandlerType = 0 /root/data/program/mycat/conf/server.xml   <property name="s ...

  10. 学习windows编程 day4 之 绘制随机矩形和peekMessage

    #include <windows.h> #include <strsafe.h> LRESULT CALLBACK WndProc(HWND hwnd, UINT messa ...