HDU 4685 Prince and Princess (2013多校8 1010题 二分匹配+强连通)
Prince and Princess
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 150 Accepted Submission(s): 46
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.
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.
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.
4 4
2 1 2
2 1 2
2 2 3
2 3 4
1 2
2 1 2
2 1 2
2 1 2
1 3
1 4
Case #2:
2 1 2
主要构图转化的思路很神奇,我看了题解才会的,T_T
首先n,m个点做一次二分匹配,得到匹配数最大为res. 相当于右边有m-res个点没有匹配,左边有n-res个点没有匹配。
所以在左加m-res个点,和右边所有相连。
在右边加n-res个点,个左边所有相连。
然后做n+m-res,n+m-res个点的二分匹配。
匹配数肯定是n+m-res;
主要是得到匹配的情况。
对于左边的点i. 把i相匹配的在右边的点,向其余和i相连的点连一有向边。
然后做强连通缩点。
如果边u-v. v和u匹配的点在一个连通分支,说明可以交换,可以u->v组合,不影响最大匹配数
/* ***********************************************
Author :kuangbin
Created Time :2013/8/15 23:20:43
File Name :F:\2013ACM练习\2013多校8\1010.cpp
************************************************ */ #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int MAXN = ;
int uN,vN;
int g[MAXN][MAXN];
int linker[MAXN];
bool used[MAXN];
bool dfs(int u)
{
for(int v = ; v <= vN;v++)
if(g[u][v] && !used[v])
{
used[v] = true;
if(linker[v] == - || dfs(linker[v]))
{
linker[v] = u;
return true;
}
}
return false;
}
int hungary()
{
int res = ;
memset(linker,-,sizeof(linker));
for(int u = ; u <= uN;u++)
{
memset(used,false,sizeof(used));
if(dfs(u))res++;
}
return res;
}
int lx[MAXN];
const int MAXM = ;//边数
struct Edge
{
int to,next;
}edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc
int Index,top;
int scc;//强连通分量的个数
bool Instack[MAXN];
int num[MAXN];//各个强连通分量包含点的个数,数组编号1~scc
//num数组不一定需要,结合实际情况 void addedge(int u,int v)
{
edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++;
}
void Tarjan(int u)
{
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for(int i = head[u];i != -;i = edge[i].next)
{
v = edge[i].to;
if( !DFN[v] )
{
Tarjan(v);
if( Low[u] > Low[v] )Low[u] = Low[v];
}
else if(Instack[v] && Low[u] > DFN[v])
Low[u] = DFN[v];
}
if(Low[u] == DFN[u])
{
scc++;
do
{
v = Stack[--top];
Instack[v] = false;
Belong[v] = scc;
num[scc]++;
}
while( v != u);
}
}
void solve(int N)
{
memset(DFN,,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
memset(num,,sizeof(num));
Index = scc = top = ;
for(int i = ;i <= N;i++)
if(!DFN[i])
Tarjan(i);
}
void init()
{
tot = ;
memset(head,-,sizeof(head));
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,m;
int k;
int T;
scanf("%d",&T);
int iCase = ;
while(T--)
{
iCase++;
scanf("%d%d",&n,&m);
memset(g,,sizeof(g));
int v;
for(int i = ;i <= n;i++)
{
scanf("%d",&k);
while(k--)
{
scanf("%d",&v);
g[i][v] = ;
}
}
uN = n;
vN = m;
int res = hungary();
uN = vN = n + m - res;
for(int i = n+;i <= uN;i++)
for(int j = ;j <= vN;j++)
g[i][j] = ;
for(int i = ;i <= uN;i++)
for(int j = m+;j <= vN;j++)
g[i][j] = ;
hungary();
memset(lx,-,sizeof(lx));
for(int i = ;i <= vN;i++)
if(linker[i] != -)
lx[linker[i]] = i;
init();
for(int i = ;i <= uN;i++)
for(int j = ;j <= vN;j++)
if(g[i][j] && j != lx[i])
addedge(lx[i],j);
solve(vN);
printf("Case #%d:\n",iCase);
vector<int>ans;
for(int i = ;i <= n;i++)
{
ans.clear();
for(int j = ; j <= m;j++)
if(g[i][j] && Belong[j] == Belong[lx[i]])
ans.push_back(j);
int sz = ans.size();
printf("%d",sz);
for(int i = ;i < sz;i++)
printf(" %d",ans[i]);
printf("\n");
}
}
return ;
}
HDU 4685 Prince and Princess (2013多校8 1010题 二分匹配+强连通)的更多相关文章
- HDU 4705 Y (2013多校10,1010题,简单树形DP)
Y Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submiss ...
- HDU 4675 GCD of Sequence (2013多校7 1010题 数学题)
GCD of Sequence Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)T ...
- HDU 4685 Prince and Princess 二分图匹配+tarjan
Prince and Princess 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 Description There are n pri ...
- HDU 4691 Front compression (2013多校9 1006题 后缀数组)
Front compression Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Othe ...
- HDU 4679 Terrorist’s destroy (2013多校8 1004题 树形DP)
Terrorist’s destroy Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Othe ...
- HDU 4671 Backup Plan (2013多校7 1006题 构造)
Backup Plan Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total ...
- HDU 4667 Building Fence(2013多校7 1002题 计算几何,凸包,圆和三角形)
Building Fence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)To ...
- HDU 4685 Prince and Princess(二分图+强连通分量)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:给出n个王子和m个公主.每个王子有一些自己喜欢的公主可以匹配.设最大匹配为M.那么对于每个 ...
- hdu 4685 Prince and Princess(匈牙利算法 连通分量)
看了别人的题解.须要用到匈牙利算法的强连通算法 #include<cstdio> #include<algorithm> #include<vector> #pra ...
随机推荐
- FusionCharts 用法心得
现在主流的很多jQuery+js结合的图表展示插件,有HighCharts,ECharts等等,今天我们先来了解一下FusionCharts,也是一个非常不错的图表制作工具.希望我的同事以及其他需要帮 ...
- cin关闭同步[转]
很多人会说cin的速度比scanf慢很多, 其实不然. cin慢的原因主要在于默认cin与stdin总是保持同步, 这一步是消耗时间大户. 只需要加上ios::sync_with_stdio(fals ...
- csu 最优对称路径(bfs+记忆化搜索)
1106: 最优对称路径 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 371 Solved: 77[Submit][Status][Web Boar ...
- MVC – 9.mvc整体请求流程
1.请求管道 2~5微软自己的验证,我们一般不用. 在全局配置文件中-已经配置一个路由过滤器-为第7个事件注册了路由方法 1.在application_start中向静态路由表注册了路由数据,在管道第 ...
- 20169211《Linux内核原理与分析》第二周作业
<linux内核分析>实验一实验报告 <linux内核设计与实现>第1.2.18章学习总结 一.<linux内核分析>实验一实验报告 在进行实验楼操作 ...
- .htaccess文件
前言 看了几篇文章,发现自己对于如何维护普通的服务器安全完全不会,先从简单的.htaccess来研究吧 .htaccess文件的作用,就是更改httpd.ini文件中的配置,但作用范围仅限当前文件夹 ...
- Python函数系列-迭代器,生成器
一 迭代器 一 迭代的概念 #迭代器即迭代的工具,那什么是迭代呢?#迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值 while True: #只是单纯地重复,因而不 ...
- 验证码无法显示:Could not initialize class sun.awt.X11GraphicsEnvironment 解决方案
一.原因现象:图下图 二.原因导致: 经过Google发现很多人也出现同样的问题.从了解了X11GraphicEnvironment这个类的功能入手,一个Java服务器来处理图片的API基本上是需要运 ...
- vue 阻止表单默认事件
方式一: <form autocomplete="off" @submit.prevent="onSubmit"> <input type=& ...
- C# 消除累计误差的倒计时
使用 C# 中自带的各种 timer 计时,都会有累计误差,以下代码实现了一种消除累计误差的方法,使得每次计时的误差,空值在 100 ms 以内(可以通过修改代码提升精度.) 对于精度要求在秒级别的简 ...