hdu 4685 简单匹配+Tarjan算法
思路:首先看到这题以为能用poj1904的模版直接A掉,WA了几次,然后又TLE了几次。还是想到了正解。
一开始我想的大致方向已经是对的了。先是由王子向每个喜欢的公主建边,再求一次最大匹配,找出匹配后,由匹配的公主向王子建边。
但可能会有没有匹配到的公主和王子,那么这个王子可以和任何它喜欢的公主结婚,这个公主也可以和任何喜欢她的王子结婚。
因为这些不在匹配中的点,加到匹配中后,减少的匹配数和增加的匹配数都是1。
我们也就想像poj1904那样,将他们变为一个强连通分量,我开始出错就在这。
直接在原图上将他们建边变为强连通分量会使原图性质发生改变。
所有我们对每个没有匹配的公主,建一个虚拟的王子,让他们变成匹配,然后由这个虚拟王子向每个公主建边。
对每个没有匹配的王子,建一个虚拟的公主,让他们变成匹配,然后每个王子向这个虚拟公主建边。
求一个Tarjan,判断是否为1个强连通分量即可。
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<cmath>
- #include<vector>
- #define Max(a,b) ((a)>(b)?(a):(b))
- #define Min(a,b) ((a)<(b)?(a):(b))
- #define Maxn 2010
- #define Maxm 400010
- 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[Maxm];
- 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,j,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 ;
- }
hdu 4685 简单匹配+Tarjan算法的更多相关文章
- HDU 1269 迷宫城堡 tarjan算法求强连通分量
基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等, ...
- hdu 4685 二分匹配+强连通分量
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 题解: 这一题是poj 1904的加强版,poj 1904王子和公主的人数是一样多的,并且给出 ...
- H - Prince and Princess - HDU 4685(二分匹配+强连通分量)
题意:有N个王子M个公主,王子喜欢一些公主,而且只能是王子喜欢的人,他们才可以结婚,现在让他们尽可能多的结婚的前提下找出来每个王子都可以和谁结婚. 分析:先求出来他们的最大匹配,因为给的数据未必是完备 ...
- Prince and Princess HDU - 4685(匹配 + 强连通)
Prince and Princess Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Othe ...
- tarjan算法讲解。
tarjan算法讲解. 全网最详细tarjan算法讲解,我不敢说别的.反正其他tarjan算法讲解,我看了半天才看懂.我写的这个,读完一遍,发现原来tarjan这么简单! tarjan算法,一个关 ...
- (转)全网最!详!细!tarjan算法讲解
byhttp://www.cnblogs.com/uncle-lu/p/5876729.html 全网最详细tarjan算法讲解,我不敢说别的.反正其他tarjan算法讲解,我看了半天才看懂.我写的这 ...
- [转]全网最!详!细!tarjan算法讲解
转发地址:https://blog.csdn.net/qq_34374664/article/details/77488976 原版的地址好像挂了..... 看到别人总结的很好,自己就偷个懒吧..以下 ...
- 【转载】全网最!详!细!tarjan算法讲解。
转自http://www.cnblogs.com/uncle-lu/p/5876729.html [转载]全网最!详!细!tarjan算法讲解.(已改正一些奥妙重重的小错误^_^) 全网最详细tarj ...
- 全网最!详!细!tarjan算法讲解。——转载自没有后路的路
全网最!详!细!tarjan算法讲解. 全网最详细tarjan算法讲解,我不敢说别的.反正其他tarjan算法讲解,我看了半天才看懂.我写的这个,读完一遍,发现原来tarjan这么简单! tarj ...
随机推荐
- Linux下的vi编辑命令中查找·替换详解
一.查找 查找命令 /pattern<Enter> :向下查找pattern匹配字符串 ?pattern<Enter>:向上查找pattern匹配字符串 使用了查找命令之后,使 ...
- thymeleaf中的条件判断用法
一.简单的条件:“if”和“unless” th:if用法实例: <table> <tr> <th>NAME</th> <th>PRICE& ...
- [iOS UI进阶 - 2.0] 彩票Demo v1.0
A.需求 1.模仿“网易彩票”做出有5个导航页面和相应功能的Demo 2.v1.0 版本搭建基本框架 code source:https://github.com/hellovoidworld/H ...
- get和eq的区别
<p style="color:yellow">绯雨</p> //使用eq来获得第一个p标签的color值: console.log().css(" ...
- HDU 3668 Volume (数学,积分)
题意:求图中交叉圆柱体的体积! 析:大体思路很明确,把两个圆柱的体积加起来 减去中间公共部分的即可!第一步首先得想到公共部分是一个怎样的图形.这个在高数下册例题中有讲到! 中间实线部分就是第一卦限内的 ...
- c# 使用ChartDirector绘图的一些个人体会
c# 使用ChartDirector绘图的一些个人体会 引言: 最近给客户做一个B/S架构的证券交易大屏幕软件,其中用到对证券指数的走势以及成交量的图形绘制,由于客户要求图形的清晰而且要做 ...
- 在Hibernate中使用HibernateTemplate来进行包含sql语句的查询
/** * 使用sql语句进行查询操作 * @param sql * @return */ public List queryWithSql(final Stri ...
- UVa532 Dungeon Master 三维迷宫
学习点: scanf可以自动过滤空行 搜索时要先判断是否越界(L R C),再判断其他条件是否满足 bfs搜索时可以在入口处(push时)判断是否达到目标,也可以在出口处(pop时) #i ...
- PostgreSQL中如何查询在当前的哪个数据库中
[pgsql@localhost bin]$ ./psql -d tester psql () Type "help" for help. tester=# select curr ...
- 配置iSCSI多路径
1.添加MPIO功能,完成后打开MPIO进行配置,添加对iSCSI多路径的支持,如下图表示已经添加完成后灰色不可选,再打开 MPIO设备 标签页可以看到已安装完成的MPIO所支持的设备: