题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685

题意:给出n个王子和m个公主。每个王子有一些自己喜欢的公主可以匹配。设最大匹配为M。那么对于每个王子,可以选择哪些自己喜欢的公主使得选择之后最大匹配仍为M?

思路:(1)首先,想到的一个方法是先求一次最大匹配。然后枚举每个王子喜欢的公主作为该王子的匹配,判断能否为之前匹配该公主的王子重新找到一个匹配。这样的复杂付太大。

(2)改进:做法是先求一次最大匹配设为cnt,那么左边有n-cnt个王子还未匹配,右边有m-cnt个公主还未匹配,因此我们将左侧增加m-cnt个虚拟王子,虚拟王子与右边所有公主连边;右边增加n-cnt个虚拟公主,虚拟公主与左边所有王子连边,这样我们就得到一个两边各有M=n+m-cnt的二分图,且该二分图是一个完美匹配。也就是每个王子都有一个匹配的公主。现在,我们将每个王子匹配的公主向该王子喜欢的公主连边(建一个新图g),然后求g的强连通分量。那么与每个王子之前匹配的公主在一个强连通分量里的公主都可以作为该王子的匹配使得最大匹配不变。为什么是这样的呢?我们想想(1)中的方法,设王子i之前的匹配为p[i],现在为王子i选择一个新的公主j,那么我们若能为p[i]重新找到一个王子k,那么实质上就是找到另一个王子互换两个两个王子喜欢的公主。因此两公主若在一个强连通分量里,那么王子由之前的匹配公主A选择公主B时,A也能找到另一个匹配,因为B能够通过某些路径到达A,等价于这条环上所有王子的匹配都后移一个人而已。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <map>
#include <ctype.h>
#include <time.h>#define abs(x) ((x)>=0?(x):-(x))
#define i64 long long
#define u32 unsigned int
#define u64 unsigned long long
#define clr(x,y) memset(x,y,sizeof(x))
#define CLR(x) x.clear()
#define ph(x) push(x)
#define pb(x) push_back(x)
#define Len(x) x.length()
#define SZ(x) x.size()
#define PI acos(-1.0)
#define sqr(x) ((x)*(x))
#define MP(x,y) make_pair(x,y)
#define EPS 1e-10#define FOR0(i,x) for(i=0;i<x;i++)
#define FOR1(i,x) for(i=1;i<=x;i++)
#define FOR(i,a,b) for(i=a;i<=b;i++)
#define FORL0(i,a) for(i=a;i>=0;i--)
#define FORL1(i,a) for(i=a;i>=1;i--)
#define FORL(i,a,b)for(i=a;i>=b;i--)#define rush() int CC;for(scanf("%d",&CC);CC--;)
#define Rush(n)  while(scanf("%d",&n)!=-1)
using namespace std;void RD(int &x){scanf("%d",&x);}
void RD(i64 &x){scanf("%I64d",&x);}
void RD(u64 &x){scanf("%I64u",&x);}
void RD(u32 &x){scanf("%u",&x);}
void RD(double &x){scanf("%lf",&x);}
void RD(int &x,int &y){scanf("%d%d",&x,&y);}
void RD(i64 &x,i64 &y){scanf("%lld%lld",&x,&y);}
void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}
void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}
void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}
void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}
void RD(i64 &x,i64 &y,i64 &z){scanf("%lld%lld%lld",&x,&y,&z);}
void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}
void RD(char &x){x=getchar();}
void RD(char *s){scanf("%s",s);}
void RD(string &s){cin>>s;}void PR(int x) {printf("%d\n",x);}
void PR(int x,int y) {printf("%d %d\n",x,y);}
void PR(i64 x) {printf("%lld\n",x);}
void PR(i64 x,i64 y) {printf("%lld %lld\n",x,y);}
void PR(u32 x) {printf("%u\n",x);}
void PR(u64 x) {printf("%llu\n",x);}
void PR(double x) {printf("%.3lf\n",x);}
void PR(double x,double y) {printf("%.5lf %.5lf\n",x,y);}
void PR(char x) {printf("%c\n",x);}
void PR(char *x) {printf("%s\n",x);}
void PR(string x) {cout<<x<<endl;}void upMin(int &x,int y) {if(x>y) x=y;}
void upMin(i64 &x,i64 y) {if(x>y) x=y;}
void upMin(double &x,double y) {if(x>y) x=y;}
void upMax(int &x,int y) {if(x<y) x=y;}
void upMax(i64 &x,i64 y) {if(x<y) x=y;}
void upMax(double &x,double y) {if(x<y) x=y;}const int mod=1000000007;
const i64 inf=((i64)1)<<60;
const double dinf=1000000000000000000.0;
const int INF=100000000;
const int N=1005;vector<int> g[N],ans[N];int dfn[N],low[N],visit[N],num,id,color[N];
stack<int> S;int n,m;
int G[N][N];
int match[N],X,p[N];
int M;int DFS(int u)
{int i;FOR1(i,M) if(G[u][i]&&X!=visit[i]){visit[i]=X;if(match[i]==-1||DFS(match[i])){match[i]=u;p[u]=i;return 1;}}return 0;
}void dfs(int u)
{dfn[u]=low[u]=++id;S.push(u);int i,v;FOR0(i,SZ(g[u])){v=g[u][i];if(!dfn[v]){dfs(v);upMin(low[u],low[v]);}else if(X!=visit[v]){upMin(low[u],dfn[v]);}}if(low[u]==dfn[u]){num++;do{v=S.top();S.pop();visit[v]=X;color[v]=num;}while(u!=v);}
}int main()
{int Num=0;rush(){RD(n,m);int i,j,k,x;clr(G,0);FOR1(i,n){RD(k);while(k--) RD(x),G[i][x]=1;}    clr(match,-1); clr(p,-1);int cnt=0;M=m;FOR1(i,n) X++,cnt+=DFS(i);M=n+m-cnt;for(i=n+1;i<=M;i++) FOR1(j,M) G[i][j]=1;for(i=m+1;i<=M;i++) FOR1(j,M) G[j][i]=1;clr(match,-1); clr(p,-1);FOR1(i,M) X++,DFS(i);FOR1(i,M) g[i].clear(),ans[i].clear();FOR1(i,M) {FOR1(j,M) if(p[i]!=j&&G[i][j]) {g[p[i]].pb(j);}}clr(dfn,0); X++; id=num=0;FOR1(i,M) if(!dfn[i]) dfs(i);FOR1(i,n) FOR1(j,m) if(G[i][j]&&color[j]==color[p[i]]){ans[i].pb(j);}printf("Case #%d:\n",++Num);FOR1(i,n) {printf("%d",(int)SZ(ans[i]));FOR0(k,SZ(ans[i])) printf(" %d",ans[i][k]);puts("");}}
}

  

HDU 4685 Prince and Princess(二分图+强连通分量)相关推荐

  1. HDU 4685 Prince and Princess(二分匹配加点建图+强连通分量)

    题目链接 Problem Description There are n princes and m princesses. Princess can marry any prince. But pr ...

  2. HDU 4685. Prince and Princess

    链接 http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意 nnn 个王子,mmm 个公主,每个王子可以娶他喜欢的公主中的一个,每个公主只能嫁个一个王子, ...

  3. HDU - 4685 Prince and Princess(强连通缩点+二分图完备匹配)

    题目链接:点击查看 题目大意:给出n个王子和m个公主,每个王子都有喜欢的公主,题目需要我们在尽可能多的王子可以匹配到喜欢的公主的情况下,求出每个王子所能娶的所有公主,必须保证王子娶了其中任何一个之后, ...

  4. HDU 3861 The King’s Problem 强连通分量 最小路径覆盖

    先找出强连通分量缩点,然后就是最小路径覆盖. 构造一个二分图,把每个点\(i\)拆成两个点\(X_i,Y_i\). 对于原图中的边\(u \to v\),在二分图添加一条边\(X_u \to Y_v\ ...

  5. 迷宫城堡 HDU - 1269 (塔尖算法求强连通分量)

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

  6. HDU4685:Prince and Princess(二分图匹配+tarjan)

    Prince and Princess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

  7. hdu 5420 Victor and Proposition 线段树建图+强连通分量

    题意: http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=620&pid=1003 题目求有多少对互为充要 ...

  8. 有向图 加最少的边 成为强连通分量的证明 poj 1236 hdu 2767

    poj 1236: 题目大意:给出一个有向图, 任务一: 求最少的点,使得从这些点出发可以遍历整张图  任务二: 求最少加多少边 使整个图变成一个强连通分量. 首先任务一很好做, 只要缩点 之后 求 ...

  9. hdu 1269(Tarjan求强连通分量)

    这道题目就是求强连通分量... 这里采用的是Tarjan算法:http://m.blog.csdn.net/blog/qq574857122/16361033 AC代码: #include<io ...

最新文章

  1. @AUTORELEASEPOOL
  2. 51单片机系列命名规则
  3. telegraf输出MySQL_Grafana+influxdb+telegraf初探-快速监控主机与mysql
  4. 【记录】启用Windows 10下的linux子系统
  5. python * args和** kwargs的用法
  6. 零基础学云计算怎么样?2020年云计算学习路线
  7. 清平乐·风鬟雨鬓 [清] 纳兰性德
  8. powershell / ps脚本ps1中.exe(可执行文件)没反应
  9. Unity3D 拆包工具 AssetStudio 编译构建
  10. 最简单DIY基于Android系统的万能蓝牙设备智能遥控器
  11. 大学计算机基础通俗易懂教材,大学计算机基础(21世纪高等学校计算机规划教材)...
  12. sql 语句高级用法常用合集
  13. 共享电单车重蹈覆辙:新车投放半年就进“坟场”
  14. layui的layer弹出层和form表单
  15. MIT人工智能实验室:如何做研究
  16. 域格LPM2100 me NB模块PSM相关问题
  17. tensorflow-----张量的合并
  18. React学习七(React Hooks)
  19. mysql高级 tigger触发器 --[2]
  20. 淘宝要社交:改变买家购买方式 取消商品排名(转载)

热门文章

  1. 不用电脑怎么恢复微信删除的聊天记录的方法
  2. vim 从嫌弃到依赖(23)——最后的闲扯
  3. EVE-NG模拟器安装教程
  4. Opencv 打开笔记本摄像头
  5. 数格子算面积的方法_一篇文章让孩子轻松掌握,不规则图形面积数格子的技巧...
  6. 沙拉查词——网页翻译神器,哪里不会点哪里
  7. rosparam和ROS参数服务器的使用(C++ Python)
  8. Redis-全面详解(学习总结---从入门到深化)
  9. 小程序不引入基础组件实现weui使用(附加小程序换行显示)
  10. Android手机为什么不同GPU游戏兼容性差别巨大