题意:婚配问题,但是题目并不要求输出最大匹配值,而是让我们输出,一个王子可以与哪些王妃婚配而不影响最大匹配值。

  解决办法:先求一次最大匹配,如果有两个已经匹配的王妃,喜欢她们两个的有两个或者以上相同的王子,那她们两个是可以交换的,对于前面的王子来说,他与这两个王妃中的任何一个匹配都不会影响最大匹配值,因为总有人把位置补上。那什么样的王妃才是可以交换的王妃呢?我们在这个王子已经匹配的王妃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(二分匹配+强联通分量)的更多相关文章

  1. HDU 4685 Prince and Princess 二分图匹配+tarjan

    Prince and Princess 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 Description There are n pri ...

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

  3. HDU 4685 Prince and Princess(二分图+强连通分量)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:给出n个王子和m个公主.每个王子有一些自己喜欢的公主可以匹配.设最大匹配为M.那么对于每个 ...

  4. hdu 4685 Prince and Princess(匈牙利算法 连通分量)

    看了别人的题解.须要用到匈牙利算法的强连通算法 #include<cstdio> #include<algorithm> #include<vector> #pra ...

  5. HDU 4685 Prince and Princess

    强连通分量,看大神的题解才会写的.... http://www.cnblogs.com/kuangbin/p/3261157.html 数据量有点大,第一次Submit 2995ms过的,时限3000 ...

  6. HDU 1269 迷宫城堡 【强联通分量(模版题)】

    知识讲解: 在代码里我们是围绕 low 和 dfn 来进行DFS,所以我们务必明白 low 和 dfn 是干什么的? 有什么用,这样才能掌握他.   1.  dfn[]  遍历到这个点的时间 2.   ...

  7. HDU 5934 强联通分量

    Bomb Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  8. 【强联通图 | 强联通分量】HDU 1269 迷宫城堡 【Kosaraju或Tarjan算法】

      为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明 ...

  9. Kosaraju算法---强联通分量

    1.基础知识 所需结构:原图.反向图(若在原图中存在vi到vj有向边,在反向图中就变为vj到vi的有向边).标记数组(标记是否遍历过).一个栈(或记录顶点离开时间的数组).      算法描叙: :对 ...

随机推荐

  1. ios 字符串的操作汇总

    //将NSData转化为NSString        NSString* str = [[NSString alloc] initWithData:response encoding:NSUTF8S ...

  2. 在cmd模式下对mysql的操作语句

    A.window下的语句 1.mysqld -install     //安装mysql服务 2.mysqld -remove //卸载mysql服务 3.net start mysql //启动服务 ...

  3. Session和Cookie的使用总结

    Session和Cookie的使用总结: Session和cookie都是asp.Net中的内置对象,至于他们有什么区别,在这里就不在多说,现在来说说一些比较实用点的东西: 我们知道网站都有一个后台管 ...

  4. 3.Perl 多线程:Threads(exit thread_only)

    还可以在导入threads模块时设置: use threads ('exit' => 'thread_only');

  5. python&MongoDB

    1 #!/usr/bin/python 2 #-*- coding:utf-8 3 import pymongo 4 connection=pymongo.MongoClient() 5 tdb=co ...

  6. 二十一、oracle pl/sql分类一 存储过程

    存储过程用于执行特定的操作,当建立存储过程时,既可以指定输入参数(in),也可以指定输出参数(out),通过在过程中使用输入参数,可以将数据传递到执行部分:通过使用输出参数,可以将执行部分的数据传递到 ...

  7. android Handler vs Timer

    Handler vs Timer 在我们Android开发过程中,经常需要执行一些短周期的定时任务,这时候有两个选择Timer或者Handler.然而个人认为: Handler 在多个方面比Timer ...

  8. ZUFE OJ 2288 God Wang I

    Description God Wang 是ZUFE的神犇,有一天他想到一种神奇的变换,并且将它命名为GodW变换 对于一个数字n,该变换后的值GodW(n)为,先令X=n 第一步,如果X为个位数,G ...

  9. 理解VMware虚拟机下网络连接的三种模式(如何配置虚拟机上网)

    很多朋友都用vmware来测试不同的系统,我结合自己的经验谈一下对网络设置的理解,不对的地方请指正. bridge:这种方式最简单,直接将虚拟网卡桥接到一个物理网卡上面,和linux下一个网卡 绑定两 ...

  10. java方法中只有值传递,没有引用传递

    public class Example { String testString = new String("good"); char[] testCharArray = {'a' ...