hdu 4685 (最大匹配+强连通分量)
来源:互联网 发布:数据采集卡的使用 编辑:程序博客网 时间:2024/06/01 10:52
Sample Input
24 42 1 22 1 22 2 32 3 41 22 1 2
Sample Output
Case #1:2 1 22 1 21 31 4Case #2:2 1 2题意:有n个王子和m个公主,每个王子都喜欢若干个公主,王子只能和他喜欢的公主结婚,而公主可以和任一个王子结婚。给出每个王子喜欢的公主,这样可以得到一个最大配对数。对于每个王子,现在要分别输出每个王子能和哪些公主结婚,要求王子和这些公主中任一个结婚后,不会影响原先的最大配对数。思路:这道题和poj1904(poj1904的解法)很相似,解法也是差不多的,但是这道题王子和公主的数量不一样,而且不一定有完美匹配。所以我们要虚拟出一些人出来构成完美匹配。先将每个王子与他喜欢的女人连一条有向边,求一次最大匹配。对于每个没有匹配到的王子,虚拟出一个公主,这个公主被所有王子喜欢,所以所有的王子都要连一条有向边到这个虚拟的公主。对于每个没有匹配到的公主,虚拟出一个王子,这个王子喜欢所有公主,所以这个王子要连一条有向边到所有的公主。最后对于每个公主(包括虚拟的),都要连一条有向边到与她配对的王子。构图完成后,缩点求强连通分量,每个王子都可以与和他在同一个强连通分量里的所有公主结婚,当然不能是虚拟的公主。#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <queue>#include <vector>#include <cmath>#include <cstdlib>#include <map>#define L(rt) (rt<<1)#define R(rt) (rt<<1|1)#define ll long longusing namespace std;const int maxn=2005;struct node{ int v,next;} edge[maxn*maxn];int G[maxn],matchn[maxn],matchm[maxn],ans[maxn];int low[maxn],dfn[maxn],scc[maxn],stack[maxn];bool vis[maxn],ins[maxn];int n,m,num,nn,top,snum,cnt,tot;void init(){ memset(G,-1,sizeof(G)); num=0;}void add(int u,int v) //建动态链表,有向图{ edge[num].v=v; edge[num].next=G[u]; G[u]=num++;}void input(){ int k,v; scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { scanf("%d",&k); while(k--) { scanf("%d",&v); add(i,v+n); //公主标号是n+1~n+m } }}bool find(int u) //匹配{ for(int i=G[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; if(!vis[v]) { vis[v]=true; if(matchm[v]==-1||find(matchm[v])) { matchm[v]=u; //公主v匹配王子u matchn[u]=v; //王子u匹配公主V return true; } } } return false;}void MMG(){ int ans=0; memset(matchn,-1,sizeof(matchn)); memset(matchm,-1,sizeof(matchm)); for(int i=1; i<=n; i++) { memset(vis,false,sizeof(vis)); if(find(i)) ans++; }}void make_graph() //扩图{ tot=n+m; for(int i=1; i<=n; i++) if(matchn[i]==-1) //王子没有匹配到公主的 { ++tot; //建一个虚拟公主 matchn[i]=tot; matchm[tot]=i; for(int k=1; k<=n; k++) //并且这个公主受所有王子喜欢.. add(k,tot); } for(int i=n+1; i<=n+m; i++) if(matchm[i]==-1) //公主没有王子跟她匹配的 { ++tot; //建虚拟王子 matchn[tot]=i; matchm[i]=tot; for(int k=n+1; k<=n+m; k++) add(tot,k); //王子是喜欢所有公主的 } for(int i=1; i<=tot; i++) //找到公主有匹配的,建公主到王子的有向边 if(matchm[i]!=-1) add(i,matchm[i]);}void dfs(int u) //球强连通分量{ int x; low[u]=dfn[u]=++cnt; stack[top++]=u; ins[u]=true; for(int i=G[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; if(!dfn[v]) { dfs(v); low[u]=min(low[u],low[v]); } else if(ins[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]) //得到一个关节点, { snum++; //一个强连通分量 do //这个图分量的成员出栈 { x=stack[--top]; ins[x]=false; scc[x]=snum; //x是在snum图分量中 } while(x!=u); }}void tarjan(){ memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(ins,false,sizeof(ins)); top=cnt=snum=0; for(int i=1; i<=tot; i++) if(!dfn[i]) dfs(i);}void solve(){ for(int u=1; u<=n; u++) { int cc=0; for(int i=G[u]; i!=-1; i=edge[i].next) //每个王子,能取的公主 { int v=edge[i].v; if(scc[u]==scc[v]&&v<=n+m) //王子和公主在一个图分量 , 且这个公主不是虚拟公主 ans[cc++]=v-n; // v-n 个公主 } sort(ans,ans+cc); //从小到大输出 printf("%d",cc); for(int i=0; i<cc; i++) printf(" %d",ans[i]); printf("\n"); }}int main(){ //freopen("1","r",stdin); int t,c=0; scanf("%d",&t); while(t--) { init(); input(); MMG(); make_graph(); tarjan(); printf("Case #%d:\n",++c); solve(); } return 0;}
- hdu 4685 (最大匹配+强连通分量)
- hdu 4685(匹配+强连通分量)
- HDU 4685 Prince and Princess(最大匹配+强连通分量)
- HDU - 1269【Tarjan最大强连通分量】
- hdu 4685 Prince and Princess(最大匹配+强连通)
- 强连通分量+二分匹配
- hdu 3861强连通分量+最小图匹配
- HDU 4685 Prince and Princess (二分图匹配 + 强连通分量)
- HDU-4685-Prince and Princess(二分匹配+强连通分量)
- hdu 4685 Prince and Princess 【匈牙利算法-匹配、强连通分量-Tarjan-缩点】
- hdu 3072(强连通分量)
- hdu 2767(强连通分量)
- hdu 1269 强连通分量
- HDU 1827 强连通分量
- HDU 1269 强连通分量
- hdu-4612-强连通分量
- HDU 2767 强连通分量
- hdu 2767强连通分量
- iOS学习笔记13—iOS框架总结
- 马上着手开发 iOS 应用程序 (Start Developing iOS Apps Today)——程序设计语言
- form单个字段传数组
- 常常忘记的C++基础知识及VS2008的相关操作
- UVA10250-The Other Two Trees
- hdu 4685 (最大匹配+强连通分量)
- 马上着手开发 iOS 应用程序 (Start Developing iOS Apps Today)——基本任务
- [zoj 3551]Bloodsucker[概率DP]
- 马上着手开发 iOS 应用程序 (Start Developing iOS Apps Today)——框架
- 关于黄路对他人进行恶意诋毁!人身攻击!威胁的说明!
- 总结 JSP与 servlet之间的传值
- 数组
- OSPF身份验证
- hdu-统计难题