这两道题差不多,POJ这道我很久以前就做过,但是比赛的时候居然没想起来。。

POJ 这道题的题意是,N个王子每个人都有喜欢的公主,当他们选定一个公主结婚时,必须是的剩下的人也能找到他喜欢的公主结婚。

思路,首先对于王子,对于每一个他喜欢的公主,直接连边,然后再根据已经给出的匹配方案,建立公主->王子的边。

最后求出SCC后在同一强联通分量里的王子和公主就可以了。

代码就不贴了

下面再讲一下HDU 4685这道题,两道题的唯一区别就是,上一道题,每个公主到王子的匹配方案都是给出的,是一定存在的,那是因为公主和王子的个数是相同的。

但是这道题公主和王子的个数不同,就无法做到两两匹配,必然存在光棍的情况。

光棍其实挺正常的,但是对于这道题,我们就需要虚拟一些王子和公主出来。

一个王子没有匹配的话,那么虚拟一个公主出来,表示所有的王子都喜欢这个公主,同理虚拟出王子的情况。

那么在求出匹配之后,我们就可以根据这些匹配来建立公主->王子的边,然后操作就和上一题一样了。

代码:

#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <ctime>
#define Max 2505
#define FI first
#define SE second
#define ll long long
#define PI acos(-1.0)
#define inf 0x3fffffff
#define LL(x) ( x << 1 )
#define bug puts("here")
#define PII pair<int,int>
#define RR(x) ( x << 1 | 1 )
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i ) using namespace std; inline void RD(int &ret) {
char c;
int flag = 1 ;
do {
c = getchar();
if(c == '-')flag = -1 ;
} while(c < '0' || c > '9') ;
ret = c - '0';
while((c=getchar()) >= '0' && c <= '9')
ret = ret * 10 + ( c - '0' );
ret * flag ;
} inline void OT(int a) {
if(a >= 10)OT(a / 10) ;
putchar(a % 10 + '0') ;
} inline void OT(double a) {
char x[111] ;
sprintf(x , "%f" , a) ;
printf("%s\n",x) ;
}
inline void RD(double &ret) {
char c ;
int flag = 1 ;
do {
c = getchar() ;
if(c == '-')flag = -1 ;
} while(c < '0' || c > '9') ;
ll fuck1 = c - '0' ;
while((c = getchar()) >= '0' && c <= '9') {
fuck1 = fuck1 * 10 + c - '0' ;
}
ll fuck2 = 1 ;
while((c = getchar()) >= '0' && c <= '9') {
fuck1 = fuck1 * 10 + c - '0' ;
fuck2 *= 10 ;
}
ret = flag * (double)fuck1 / (double)(fuck2) ;
}
/***************************************************/
#define N 2005
int n , m ;
int fk[N] ;
int vis[N] ;
struct kdq {
int s , e , next ;
} ed[N * N] ;
int head[N] , num = 0 ;
int nn ;
int linkx[N] ,linky[N] ;
vector<int>G[N] ;
void add(int s ,int e) {
ed[num].s = s ;
ed[num].e = e ;
ed[num].next = head[s] ;
head[s] = num ++ ;
} int dfs(int now) {
int sz = G[now].size() ;
for (int i = 0 ; i < sz ; i ++ ) {
int e = G[now][i] ;
if(!vis[e]) {
vis[e] = 1 ;
if(linky[e] == -1 || dfs(linky[e])) {
linky[e] = now ;
linkx[now] = e ;
return 1 ;
}
}
}
return 0 ;
} //tarjan_define
int low[N] , dfn[N] , st[N] , belong[N] ;
int top , dp ,SCC ; void tarjan(int now) {
vis[now] = 1 ;
st[top ++ ] = now ;
dfn[now] = low[now] = dp ++ ;
for (int i = head[now] ; i != -1 ; i = ed[i].next ) {
int v = ed[i].e ;
if(dfn[v] == -1) {
tarjan(v) ;
low[now] = min(low[now] ,low[v]) ;
} else if(vis[v]) {
low[now] = min(low[now] ,dfn[v]) ;
}
}
if(low[now] == dfn[now]) {
int xx ;
SCC ++ ;
do {
xx = st[-- top ] ;
vis[xx] = 0 ;
belong[xx] = SCC ;
} while(xx != now) ;
}
} //init
void init() {
mem(linkx ,-1) ;
mem(linky ,-1) ;
mem(vis, 0) ;
mem(low,0) ;
mem(dfn ,-1) ;
mem(st ,0) ;
mem(head ,-1) ;
num = top = dp = SCC = 0 ;
}
int main() {
int T ;
#ifndef ONLINE_JUDGE
freopen("D:\\fuck.txt","r",stdin) ;
#endif
cin >> T ;
int ca = 0 ;
while(T -- ) {
RD(n) ;
RD(m) ;
int nfk = max(m , n) ;
init() ;
for (int i = 0 ; i <= N >> 1 ; i ++ ) {
G[i].clear() ;
} REP(i , 1 , n ) {
int x ;
RD(x) ;
while(x -- ) {
int y ;
RD(y) ;
add(i , nfk + y) ;
G[i].push_back(nfk + y) ;
}
}
nn = 0 ;
for (int i = 1 ; i <= nfk ; i ++ ) {
mem(vis ,0) ;
nn += dfs(i) ;
}
nn = 2 * nfk ;
for (int i = 1 ; i <= nfk ; i ++ ) { //虚拟公主
if(linkx[i] == -1) {
linkx[i] = ++ nn ;
linky[nn] = i ;
for (int j = 1 ; j <= nfk ; j ++ ) { //所有王子都喜欢这个公主
add(j , nn) ;
}
}
add(linkx[i] , i) ;
}
for (int i = nfk + 1 ; i <= nfk << 1 ; i ++ ) { //虚拟王子
if(linky[i] == -1) {
linkx[++ nn] = i ;
linky[i] = nn ;
for (int j = nfk + 1 ; j <= nfk + nfk ; j ++ ) { //这个王子喜欢所有公主
add(nn , j) ;
}
}
add(i , linky[i]) ;
}
mem(vis, 0) ;
for (int i = 1 ; i <= nn ; i ++ ) {
if(dfn[i] == -1)tarjan(i) ;
}
printf("Case #%d:\n",++ ca) ;
set<int>fk ;
__typeof(fk.begin()) it ;
for (int i = 1 ; i <= n ; i ++ ) {
fk.clear() ;
for (int j = head[i] ; ~j ; j = ed[j].next ) {
int x = belong[i] ;
int y = belong[ed[j].e] ;
if(x == y && ed[j].e <= nfk + m) {
fk.insert(ed[j].e - nfk) ;
}
}
printf("%d",fk.size()) ;
for (it = fk.begin() ; it != fk.end() ; it ++) {
printf(" %d",*it) ;
}
puts("") ;
}
}
return 0 ;
}

POJ 1904 HDU 4685的更多相关文章

  1. hdu 4685 二分匹配+强连通分量

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 题解: 这一题是poj 1904的加强版,poj 1904王子和公主的人数是一样多的,并且给出 ...

  2. hdu 4685(强连通分量+二分图)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:n个王子和m个公主,王子只能和他喜欢的公主结婚,公主可以和所有的王子结婚,输出所有王子可能 ...

  3. poj 1904(强连通分量+输入输出外挂)

    题目链接:http://poj.org/problem?id=1904 题意:有n个王子,每个王子都有k个喜欢的妹子,每个王子只能和喜欢的妹子结婚,大臣给出一个匹配表,每个王子都和一个妹子结婚,但是国 ...

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

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

  5. hdu 4685(强连通分量+二分图的完美匹配)

    传送门:Problem 4685 https://www.cnblogs.com/violet-acmer/p/9739990.html 参考资料: [1]:二分图的最大匹配.完美匹配和匈牙利算法 [ ...

  6. POJ 2104&HDU 2665 Kth number(主席树入门+离散化)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 50247   Accepted: 17101 Ca ...

  7. poj 1251 poj 1258 hdu 1863 poj 1287 poj 2421 hdu 1233 最小生成树模板题

    poj 1251  && hdu 1301 Sample Input 9 //n 结点数A 2 B 12 I 25B 3 C 10 H 40 I 8C 2 D 18 G 55D 1 E ...

  8. Eight POJ - 1077 HDU - 1043 八数码

    Eight POJ - 1077 HDU - 1043 八数码问题.用hash(康托展开)判重 bfs(TLE) #include<cstdio> #include<iostream ...

  9. POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

    求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的, ...

随机推荐

  1. android 后台代码设置动画

    1.设置旋转动画 final RotateAnimation animation =new RotateAnimation(0f,360f,Animation.RELATIVE_TO_SELF, 0. ...

  2. 【Anagrams】 cpp

    题目: Given an array of strings, return all groups of strings that are anagrams. Note: All inputs will ...

  3. 《Soft Skill》一书中的好句子

    The biggest mistake that you can make is to believe that you are working for somebody else. Job secu ...

  4. 避免JS全局变量冲突

    一.原则1.1 用匿名函数将脚本包起来1.2 使用命名空间(多级) 二.改进过程 2.1 原始数据(a.js和b.js都有全局变量window.a,导致冲突,全局变量属于window) //a.js& ...

  5. Leetcode#140 Word Break II

    原题地址 动态规划题 令s[i..j]表示下标从i到j的子串,它的所有分割情况用words[i]表示 假设s[0..i]的所有分割情况words[i]已知.则s[0..i+1]的分割情况words[i ...

  6. IOS CoreData 多表查询demo解析

    在IOS CoreData中,多表查询上相对来说,没有SQL直观,但CoreData的功能还是可以完成相关操作的. 下面使用CoreData进行关系数据库的表与表之间的关系演示.生成CoreData和 ...

  7. Linux常用命令大全(转载)

    系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS ...

  8. 17+个ASP.NET MVC扩展点,含源码{转}

    1.自定义一个HttpModule,并将其中的方法添加到HttpApplication相应的事件中!即:创建一个实现了IHttpmodule接口的类,并将配置WebConfig.在自定义的HttpMo ...

  9. Android 添加Button事件

    protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentV ...

  10. HDU4010 Query on The Trees(LCT)

    人生的第一道动态树,为了弄懂它的大致原理,需要具备一些前置技能,如Splay树,树链剖分的一些概念.在这里写下一些看各种论文时候的心得,下面的代码是拷贝的CLJ的模板,别人写的模板比较可靠也方便自己学 ...