HDU 4685 Prince and Princess(二分匹配+强联通分量)
题意:婚配问题,但是题目并不要求输出最大匹配值,而是让我们输出,一个王子可以与哪些王妃婚配而不影响最大匹配值。
解决办法:先求一次最大匹配,如果有两个已经匹配的王妃,喜欢她们两个的有两个或者以上相同的王子,那她们两个是可以交换的,对于前面的王子来说,他与这两个王妃中的任何一个匹配都不会影响最大匹配值,因为总有人把位置补上。那什么样的王妃才是可以交换的王妃呢?我们在这个王子已经匹配的王妃match[i]与他喜欢的王妃v连一条有向边,那样处在一个强联通分量的两个王妃就是可以相互交换的。
下面处理没有匹配的王妃的情况,假设最大匹配值为res,那我们在左边加上m-res个虚拟点,右边加上n-res个虚拟点,左边的虚拟点喜欢所有的王妃,右边的虚拟点被所有的王子喜欢,再求一次最大匹配,然后把边连上。这种方法很巧妙,因为一个没有匹配的王妃,所有的王子都可以跟她匹配而不影响最大值,把她加到强联通分量中的方法就是加这种虚拟点。
注意:我们在联通分量里建的边还是挺多的,我用的maxn*2就WA了,后来干脆改成maxn*maxn,就AC了。
#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<cstring>
using namespace std;
#define maxn 2020
int map1[maxn][maxn];
int link[maxn],vis[maxn];
struct Edge
{
int to,nxt;
} edge[maxn*maxn];
int head[maxn],low[maxn],dfn[maxn],id[maxn];
int all,tot,scc;
bool hungry(int u,int m)
{
for(int i = ; i <= m; i++)
{
if(map1[u][i] && !vis[i])
{
vis[i] = ;
if(link[i]==- || hungry(link[i],m))
{
link[i] = u;
return true;
}
}
}
return false;
}
int slove(int n,int m)
{
memset(link,-,sizeof(link));
int ans = ;
for(int i = ; i <= n; i++)
{
memset(vis,,sizeof(vis));
if(hungry(i,m)) ans++;
}
return ans;
}
void addedge(int u,int v)
{
edge[tot].to = v;
edge[tot].nxt = head[u];
head[u] = tot++;
}
stack<int> s;
void init()
{
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(id,,sizeof(id));
all = ;
tot = ;
scc = ;
memset(head,-,sizeof(head));
while(!s.empty()) s.pop();
}
void tarjan(int u)
{
low[u] = dfn[u] = ++all;
s.push(u);
for(int i = head[u]; i != -; i = edge[i].nxt)
{
int v = edge[i].to;
if(!dfn[v])
{
tarjan(v);
low[u] = min(low[u],low[v]);
}
else if(!id[v]) low[u] = min(low[u],dfn[v]);
}
if(low[u] == dfn[u])
{
scc++;
int num;
while(!s.empty())
{
num = s.top();
s.pop();
id[num] = scc;
if(num == u) break;
}
}
}
int main()
{
int t,a,b,k,n,m,ca = ;
scanf("%d",&t);
while(t--)
{
memset(map1,,sizeof(map1));
scanf("%d%d",&n,&m);
for(int i = ; i <= n; i++)
{
scanf("%d",&k);
while(k--)
{
scanf("%d",&a);
map1[i][a] = ;
}
}
int match_num;
match_num = slove(n,m);
int newn,newm;
newn = newm = n+m-match_num;
for(int i = n+; i <= newn; i++)
{
for(int j = ; j <= newm; j++)
{
map1[i][j] = ;
}
}
for(int i = ; i <= newn; i++)
{
for(int j = m+; j <= newm; j++)
{
map1[i][j] = ;
}
}
match_num = slove(newn,newm);
int match[maxn];
memset(match,-,sizeof(match));
for(int i = ; i <= newm; i++)
{
match[link[i]] = i;
}
init();
for(int i = ; i <= newn; i++)
{
for(int j = ; j <= newm; j++)
{
if(map1[i][j] && match[i] != j)
{
addedge(match[i],j);
}
}
}
for(int i = ; i <= newm; i++)
{
if(!dfn[i])
{
tarjan(i);
}
}
vector<int>ve;
printf("Case #%d:\n",++ca);
for(int i = ;i <= n;i++)
{
ve.clear();
//printf("match[%d] = %d\n",i,match[i]);
for(int j = ;j <= m;j++)
{
//printf("id[%d] = %d\n",j,id[j]);
if(map1[i][j] && id[j] == id[match[i]])
{
ve.push_back(j);
}
}
int len = ve.size();
printf("%d",len);
for(int j = ;j < len;j++)
{
printf(" %d",ve[j]);
}
printf("\n");
}
}
return ;
}
HDU 4685 Prince and Princess(二分匹配+强联通分量)的更多相关文章
- HDU 4685 Prince and Princess 二分图匹配+tarjan
Prince and Princess 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 Description There are n pri ...
- 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 ...
- 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 ...
- HDU 4685 Prince and Princess
强连通分量,看大神的题解才会写的.... http://www.cnblogs.com/kuangbin/p/3261157.html 数据量有点大,第一次Submit 2995ms过的,时限3000 ...
- HDU 1269 迷宫城堡 【强联通分量(模版题)】
知识讲解: 在代码里我们是围绕 low 和 dfn 来进行DFS,所以我们务必明白 low 和 dfn 是干什么的? 有什么用,这样才能掌握他. 1. dfn[] 遍历到这个点的时间 2. ...
- HDU 5934 强联通分量
Bomb Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- 【强联通图 | 强联通分量】HDU 1269 迷宫城堡 【Kosaraju或Tarjan算法】
为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明 ...
- Kosaraju算法---强联通分量
1.基础知识 所需结构:原图.反向图(若在原图中存在vi到vj有向边,在反向图中就变为vj到vi的有向边).标记数组(标记是否遍历过).一个栈(或记录顶点离开时间的数组). 算法描叙: :对 ...
随机推荐
- Lynis 2.2.0 :面向Linux系统的安全审查和扫描工具
Lynis是一款功能非常强大的开源审查工具,面向类似Unix/Linux的操作系统.它可以扫描系统,查找安全信息.一般的系统信息.已安装软件及可用软件信息.配置错误.安全问题.没有设密码的用户帐户.错 ...
- TouchSlide滚动插件BUG
TouchSlide滚动切换效果时 nextCell设定自己的class名后无效,需要用".next"或不设置
- CSV文件解析工具
package com.common.util; import java.io.BufferedReader; import java.io.FileInputStream; import java. ...
- SQL函数学习(二):DATEADD() 函数
DATEADD() 函数在日期中添加或减去指定的时间间隔. 语法 DATEADD(datepart,number,date) date 参数是合法的日期表达式.number 是您希望添加的间隔数:对于 ...
- js控制日期选择框datetime-local和select的展开
注: js控制元素展开不受元素css属性的限制,例如opacity,z-index等 1. 使用js控制日期选择框的展开 ios: document.querySelector(".targ ...
- zstu 4215 多起点bfs
input n m 1<=n,m<=1000 n*m的地图,全为大写字母 7 10 WWWWWCCDEW WWWWCCEEEW WTWWWCCCCW WWFFFFFFWW WWFAAAA ...
- 关于GVIM的配置。
最近开始考虑从常用的 Dev-Cpp 和 Visual Studio 开发环境中转到gvim+gcc+gdb. 我一直觉得IDE很好方便,不是很明白别人这样的配置.但还是开始有意识的去尝试更换环境. ...
- HDU - 5455 Fang Fang
Problem Description Fang Fang says she wants to be remembered.I promise her. We define the sequence ...
- HOSTS文件修改后不起作用的原因
如果是通过记事本修改,其实是没有问题的,如果有问题,网上搜到的是ipconfig /flushdns之类的 如果是批量程序写的,那就要小心了, 一定要ANSI(美标格式的,忘了英文是什么来着) 保存后 ...
- MYSQL超时连接问题(com.mysql.jdbc.MysqlIO.readFully)
应用服务器连接mysql,有时候会出现以下异常: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.jav ...