【hdu】4685 Prince and Princess【二分匹配+tarjan】
来源:互联网 发布:通讯软件排名 编辑:程序博客网 时间:2024/05/16 05:58
题意:有n个王子,m个公主,每个王子有他自己喜欢的公主们,问一个王子可以匹配的公主有哪些,要求一个王子匹配一个公主后,总的可匹配数不能减少,也就是不能让别的王子的本来可以有老婆的,现在没了。
题解:题意和poj1904集合一样,只不过那题给出了完美匹配,且王子与公主都是n个,这题又加了限制,是poj1904的加强版,可以先试试那题再来做这题后好理解很多,这是poj1904的题解 http://blog.csdn.net/a709743744/article/details/52133778
现在我们在上述题解的情况下继续讲这题怎么做,我们把这题尽量转换成poj1904的形式,我们先对题目给出的条件求一次二分匹配,
假设匹配数是cnt,
对于未匹配的n-cnt个王子,我们虚拟出n-cnt个公主和他匹配,并让所有真实王子都喜欢这个虚拟公主
对于未匹配的m-cnt个公主,我们虚拟出m-cnt个王子和她匹配,并让虚拟王子喜欢所有的真实公主
这样王子和公主都有n+m-cnt个,问题就完全转换成了poj1904,然后我们就按poj1904求一遍强连通,记得最后别输出虚拟公主即可
#include<queue>#include<vector>#include<cstdio>//先用强连通缩点来化简图,然后在图上做拓扑排序,如果排序过程中,出现1个以上的点入度同时为0时,那么就不满足条件。#include<cstring>#include<algorithm>#define PB push_back#define MP make_pairusing namespace std;const int N=4010;const int inf=0x3f3f3f3f;int dfn[N],low[N],instack[N],belong[N],S[N];int index,scc,shead;vector<int>G[N];vector<pair<int,int> >E[N];void dfs(int u){ dfn[u]=low[u]=++index; S[shead++]=u; instack[u]=true; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(!dfn[v]){ dfs(v); low[u]=min(low[v],low[u]); }else if(instack[v]) low[u]=min(dfn[v],low[u]); } if(low[u]==dfn[u]){ scc++; while(1){ int tmp=S[--shead]; belong[tmp]=scc; instack[tmp]=false; if(tmp==u)break; } }}void tarjan(int n){ index=scc=shead=0; memset(dfn,0,sizeof(dfn)); memset(instack,false,sizeof(instack)); for(int i=1;i<=n;i++)if(!dfn[i])dfs(i);}int ans[N],lx[N],ly[N],used[N],n,m;bool Dfs(int u){ for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(!used[v]){ used[v]=true; if(ly[v]==-1||Dfs(ly[v])){ ly[v]=u; lx[u]=v; return true; } } } return false;}int hungry(int n){ int res=0; memset(lx,-1,sizeof(lx)); memset(ly,-1,sizeof(ly)); for(int i=1;i<=n;i++){ memset(used,0,sizeof(used)); if(Dfs(i))res++; } return res;}int main(){ int T,kase=0; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); for(int i=1;i<=(n+m)*2;i++)G[i].clear(); for(int i=1;i<=n;i++){ int x,y; scanf("%d",&x); while(x--){ scanf("%d",&y); G[i].PB(n+y); } } hungry(n); int all=n+m; for(int i=1;i<=n;i++)if(lx[i]==-1){//新增妹子 all++; lx[i]=all; ly[all]=i; for(int j=1;j<=n;j++)G[j].PB(all); } for(int j=1;j<=m;j++)if(ly[j+n]==-1){//新增王子 all++; lx[all]=j+n; ly[j+n]=all; for(int j=1;j<=m;j++)G[all].PB(j+n); } for(int i=1;i<=all;i++) if(lx[i]!=-1)G[lx[i]].PB(i); tarjan(all); printf("Case #%d:\n",++kase); for(int i=1;i<=n;i++){ int cnt=0; for(int j=0;j<G[i].size();j++){ int v=G[i][j]; if(belong[i]==belong[v]){ if(v-n<=m)ans[cnt++]=v-n; } } sort(ans,ans+cnt); printf("%d",cnt); for(int j=0;j<cnt;j++){ printf(" %d",ans[j]); } printf("\n"); } } return 0;}
0 0
- hdu 4685 Prince and Princess(Tarjan+二分匹配)
- 【hdu】4685 Prince and Princess【二分匹配+tarjan】
- hdu 4685 Prince and Princess(二分匹配+强连通)
- hdu 4685 Prince and Princess 【匈牙利算法-匹配、强连通分量-Tarjan-缩点】
- HDU 4685 Prince and Princess (二分图匹配 + 强连通分量)
- hdu 4685 Prince and Princess(二分图匹配 + 强连通)
- HDU-4685-Prince and Princess(二分匹配+强连通分量)
- HDU 4685 Prince and Princess(求所有二分图最大匹配)
- HDU 4685 Prince and Princess
- hdu 4685 Prince and Princess
- HDU 4685 Prince and Princess
- HDU 4685 Prince and Princess(二分图 + 强连通)
- hdu 4685 Prince and Princess(最大匹配+强连通)
- hdu 4685 Prince and Princess(完美匹配+SCC缩点)
- POJ 1904 King's Quest && HDU 4685 Prince and Princess (强联通解决二分图可行匹配问题)
- 【强连通】 HDU 4685 Prince and Princess
- hdu 4685 Prince and Princess(最大匹配+强连通所点,5级)
- HDU 4685 Prince and Princess(最大匹配+强连通分量)
- 常用的正则表达式大全
- bakdown.sh
- 设计模式学习笔记之建造者模式
- Android NDK开发总结
- JNI初步接触--认识、简单配置
- 【hdu】4685 Prince and Princess【二分匹配+tarjan】
- Android 向右滑动销毁(finish)Activity, 随着手势的滑动而滑动的效果
- oj:进制转换
- 图
- 如何在java中调用js方法
- hdu 5795 A Simple Nim (sg函数)
- 启发式搜索1
- leetcode Word Break
- 灰度级和像素值