POJ 1904 HDU 4685
这两道题差不多,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的更多相关文章
- hdu 4685 二分匹配+强连通分量
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 题解: 这一题是poj 1904的加强版,poj 1904王子和公主的人数是一样多的,并且给出 ...
- hdu 4685(强连通分量+二分图)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:n个王子和m个公主,王子只能和他喜欢的公主结婚,公主可以和所有的王子结婚,输出所有王子可能 ...
- poj 1904(强连通分量+输入输出外挂)
题目链接:http://poj.org/problem?id=1904 题意:有n个王子,每个王子都有k个喜欢的妹子,每个王子只能和喜欢的妹子结婚,大臣给出一个匹配表,每个王子都和一个妹子结婚,但是国 ...
- HDU 4685 Prince and Princess 二分图匹配+tarjan
Prince and Princess 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 Description There are n pri ...
- hdu 4685(强连通分量+二分图的完美匹配)
传送门:Problem 4685 https://www.cnblogs.com/violet-acmer/p/9739990.html 参考资料: [1]:二分图的最大匹配.完美匹配和匈牙利算法 [ ...
- POJ 2104&HDU 2665 Kth number(主席树入门+离散化)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 50247 Accepted: 17101 Ca ...
- 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 ...
- Eight POJ - 1077 HDU - 1043 八数码
Eight POJ - 1077 HDU - 1043 八数码问题.用hash(康托展开)判重 bfs(TLE) #include<cstdio> #include<iostream ...
- POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算
求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的, ...
随机推荐
- IE9兼容性视图与IE9标准视图
如果你使用的是IE9,那么按下F12键就会出现开发者工具,上面有两个下拉菜单:浏览器模式和文档模式.那么什么是浏览器模式?什么又是文档模式?二者有何区别? 浏览器模式用于切换IE针对该网页的默认文档模 ...
- C语言面向对象风格编程
前言 本文略谈C面向对象风格编程,如何使用过程式语言去模拟面向对象的特性?C面向对象的方式和形式很多,不一而足,本文的代码形式是模拟部分C++面向对象关键词并赋予其特性,这种方式对于初级程序员比较好理 ...
- C语言遇到的错误和解决方案~~~持续更新,记录成长的过程
1.error C2296: '&' : illegal, left operand has type 'char [3]' scanf("%d" &x); 少了一 ...
- Retry Pattern
Retry Pattern https://msdn.microsoft.com/en-us/library/dn589788.aspx https://msdn.microsoft.com/en-u ...
- 深入理解jQuery中live与bind方法的区别
本篇文章主要是对jQuery中live与bind方法的区别进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助 注意如果是通过jq添加的层和对象一定要用live(),用其他的都不起作用 ...
- 拆分Sql列中内容的拆分
拆分Sql列中内容的拆分. /*按照符号分割字符串*/ create function [dbo].[m_split](@c varchar(2000),@split varchar(2)) retu ...
- Confluence Wiki Markup & Markdown
Markup : 默认有支持 Markdown : 需先安装插件,插件下载地址: Confluence markdown : https://marketplace.atlassian.com/plu ...
- CSS3 transition规范的实际使用经验
本篇文章主要讲述CSS3 transition规范和在不同浏览器之间的使用差异,关于具体解决方法或如何规避问题的意见可以参考另一篇非常有见地的文章,“All You Need to Know Abou ...
- java 如何从配置文件(.properties)中读取内容
1.如何创建.properties文件 很简单,建立一个txt文件,并把后缀改成.properties即可 2.将.properties文件拷入src的根目录下 3..properties文件内容格式 ...
- 重载和覆盖的区别?(overload vs override)
override与overload的区别? override 表示重写,overload 表示重载.override是子类和父类之间的关系,是垂直关系:overload是同一个类中方法之间的关系,是水 ...