题意:婚配问题,但是题目并不要求输出最大匹配值,而是让我们输出,一个王子可以与哪些王妃婚配而不影响最大匹配值。
解决办法:先求一次最大匹配,如果有两个已经匹配的王妃,喜欢她们两个的有两个或者以上相同的王子,那她们两个是可以交换的,对于前面的王子来说,他与这两个王妃中的任何一个匹配都不会影响最大匹配值,因为总有人把位置补上。那什么样的王妃才是可以交换的王妃呢?我们在这个王子已经匹配的王妃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的有向边).标记数组(标记是否遍历过).一个栈(或记录顶点离开时间的数组). 算法描叙: :对 ...
随机推荐
-
C# ADO.net 数据库连接池
前一阵开发一套系统,同组的同事提供了一个数据库连接组件,是他自己封装的,使用了自定义的连接池,用着很是不爽,而且经常会因为程序不严谨的原因,导致连接池里的连接被用完,也导致其他错误,因此我想自己研究一 ...
-
Nancy之基于Nancy.Hosting.Aspnet的小Demo
近来学习了一下Nancy这个框架,感觉挺好用的,就写篇简单的文章记录一下大致用法,由于是刚接触,写的代码 可能不规范,也没有具体的分层..莫吐槽... Nancy的官网:http://nancyfx. ...
-
word2vec + transE 知识表示模型
本文主要工作是将文本方法 (word2vec) 和知识库方法 (transE) 相融合作知识表示,即将外部知识库信息(三元组)加入word2vec语言模型,作为正则项指导词向量的学习,将得到的词向量用 ...
-
说说设计模式~ 模版模式(Template)
返回目录 模版模式,又被称为模版方法模式,它可以将工作流程进行封装,并且对外提供了个性化的控制,但主流程外界不能修改,也就是说,模版方法模式中,将工作的主体架构规定好,具体类可以根据自己的需要,各自去 ...
-
Redis监控方案
Redis 监控最直接的方法当然就是使用系统提供的 info 命令来做了,你只需要执行下面一条命令,就能获得 Redis 系统的状态报告. redis-cli info 内存使用 如果 Redis 使 ...
-
Index Full Scan vs Index Fast Full Scan-1103
[Oracle] Index Full Scan vs Index Fast Full Scan作者:汪海 (Wanghai) 日期:14-Aug-2005 出处:http://spaces.msn. ...
-
Stm32高级定时器(二)
Stm32高级定时器(二) 1 主从模式:主?从? 谈论主从,可知至少有两个以上的触发或者驱动信号,stm32内部有多个定时器,可以相互之间驱动或者控制. 主模式:定时器使能只受驱动时钟控制或者输出控 ...
-
jmeter 分布式实战
最近作者在公司部署公司的分布式压力测试情况的时候,遇到了问题,什么问题呢,各种错误,于是大晚上的为了不耽误压测,我们就两个同事两台电脑搞,可是还是不行的呢,我要研究研究这个是什么梗,于是乎,大晚上加班 ...
-
2019-01-23 JavaScript实现ZLOGO: 性能改进
主攻前文吴烜:JavaScript实现ZLOGO: 界面改进与速度可调的几个性能问题 在线演示: 圈3 源码仍在: program-in-chinese/quan3 之前是在绘制过程中计算每帧需要绘制 ...
-
拷贝一张图片,从一个目录到另外一个目录下(PS:是拷贝是不是移动)
package com.lanxi.demo2_6; import java.io.File; import java.io.FileInputStream; import java.io.FileN ...