#POJ 1486 Sorting Slides (二分图完备图的必须边和最大匹配)

Sorting Slides

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 5676 Accepted: 2188

Description

Professor Clumsey is going to give an important talk this afternoon. Unfortunately, he is not a very tidy person and has put all his transparencies on one big heap. Before giving the talk, he has to sort the slides. Being a kind of minimalist, he wants to do this with the minimum amount of work possible.

The situation is like this. The slides all have numbers written on them according to their order in the talk. Since the slides lie on each other and are transparent, one cannot see on which slide each number is written.


Well, one cannot see on which slide a number is written, but one may deduce which numbers are written on which slides. If we label the slides which characters A, B, C, ... as in the figure above, it is obvious that D has number 3, B has number 1, C number 2 and A number 4.

Your task, should you choose to accept it, is to write a program that automates this process.

Input

The input consists of several heap descriptions. Each heap descriptions starts with a line containing a single integer n, the number of slides in the heap. The following n lines contain four integers xmin, xmax, ymin and ymax, each, the bounding coordinates of the slides. The slides will be labeled as A, B, C, ... in the order of the input.

This is followed by n lines containing two integers each, the x- and y-coordinates of the n numbers printed on the slides. The first coordinate pair will be for number 1, the next pair for 2, etc. No number will lie on a slide boundary.

The input is terminated by a heap description starting with n = 0, which should not be processed.

Output

For each heap description in the input first output its number. Then print a series of all the slides whose numbers can be uniquely determined from the input. Order the pairs by their letter identifier.

If no matchings can be determined from the input, just print the word none on a line by itself.

Output a blank line after each test case.

Sample Input

4
6 22 10 20
4 18 6 16
8 20 2 18
10 24 4 8
9 15
19 17
11 7
21 11
2
0 2 0 2
0 2 0 2
1 1
1 1
0

Sample Output

Heap 1
(A,4) (B,1) (C,2) (D,3)

Heap 2
none。

题目大意 : 有N个透明的卡片, 编号从1 到 N, 每个卡片都对应了某个英文字母, 由于是透明的,所以无法辨认哪个字母是属于哪张卡片(字母在卡片的范围内即为属于该卡片),现在让你输出所有的可以确定的字母属于卡片的组合,如果一个也无法确定, 输出 “none”

思路 : 在学二分图最大匹配完备图的必须边之前, 我找必须边都是通过删边,然后看删完这条边之后, 二分图是否还能达到之前的匹配数, 如果不能,说明该边是必须边, 有一道棋盘的题这样暴力做是能过的, 写这道题的时候我才知道必须边和可行边有他自己的写法。 可行边的概念是, 删除这条边之后, 二分图的最大匹配数不变, 但是他仍然可以做为二分图最大匹配中的一条边(换句话说就是存在增广路), 而必须边就是删除该边, 无法达到最大匹配。 具体做法是这样, 先跑一遍最大匹配, 然后形成了一些边, 不知道是不是必须边, 所以建一个图 :如果该边是匹配后的边, 将两点反向建图, 否则正向建图。 缩完点之后, 如果是之前最大匹配中的边, 他的两个点不在一个集合中, 那这条边一定是必须边, 而在一个集合中的,就是可行边, 不明白画几张图就会了,样例一就可以。最后处理一些细节,这道题就解决了。

Accepted code

#include<iostream>
#include<algorithm>
#include<functional>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
using namespace std;

#define sc scanf
#define ls rt << 1
#define rs ls | 1
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define MEM(x, b) memset(x, b, sizeof(x))
#define lowbit(x) ((x) & (-x))
#define P2(x) ((x) * (x))

typedef long long ll;
const int MOD = 1e9 + 7;
const int MAXN = 2e3 + 100;
const int INF = 0x3f3f3f3f;
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % MOD; b >>= 1; t = (t*t) % MOD; }return r; }

struct Edge
{
	int v, next;
}edge[MAXN << 1];
struct node
{
	int lx, rx, ly, ry; // 范围
}p[MAXN];
vector <int> e[MAXN << 1];
int head[MAXN], dfn[MAXN], low[MAXN], as[MAXN];  // as为必须边
int pre[MAXN], suo[MAXN], n, cnt, tot, scnt, X;  // pre为最大匹配的边
bool vis[MAXN];
stack <int> st;
void init() {
	for (int i = 1; i <= n; i++) e[i].clear();
	MEM(head, -1); MEM(dfn, 0); MEM(low, 0);
	MEM(vis, 0); MEM(pre, 0); MEM(suo, 0); MEM(as, 0);
	cnt = tot = scnt = 0;
}
void add(int from, int to) {
	edge[++cnt].v = to;
	edge[cnt].next = head[from];
	head[from] = cnt;
}
bool find_(int x) {
	for (int i = 0; i < SZ(e[x]); i++) {
		int vi = e[x][i];
		if (!vis[vi]) {
			vis[vi] = true;
			if (!pre[vi] || find_(pre[vi])) {
				pre[vi] = x;
				return true;
			}
		}
	}
	return false;
}
void tarjan(int x) {
	dfn[x] = low[x] = ++tot;
	vis[x] = 1; st.push(x);
	for (int i = head[x]; i != -1; i = edge[i].next) {
		int vi = edge[i].v; 
		if (!dfn[vi]) {
			tarjan(vi);
			low[x] = min(low[x], low[vi]); 
		}
		else if (vis[vi]) low[x] = min(low[x], dfn[vi]);
	}
	if (dfn[x] == low[x]) {
		scnt++;
		int k;
		do {
			k = st.top();
			st.pop();
			vis[k] = 0;
			suo[k] = scnt;  // 存到一个集合
		} while (k != x);
	}
}

int main()
{
	while (~sc("%d", &n) && n) {
		init();
		for (int i = 1; i <= n; i++) sc("%d %d %d %d", &p[i].lx, &p[i].rx, &p[i].ly, &p[i].ry);
		for (int i = n + 1; i <= 2 * n; i++) {
			int xi, yi;
			sc("%d %d", &xi, &yi);
			for (int j = 1; j <= n; j++) {
				if (xi >= p[j].lx && xi <= p[j].rx && yi >= p[j].ly && yi <= p[j].ry)
					e[j].push_back(i);  // 存边
			}
		}
		int ans = 0;
		for (int i = 1; i <= n; i++) {
			MEM(vis, 0);
			if (find_(i)) ans++;  // 先跑一遍最大匹配
		}
		for (int i = 1; i <= n; i++) {
			for (int j = 0; j < SZ(e[i]); j++) {
				int ui = i, vi = e[i][j];
				if (pre[vi] == ui) add(vi, ui); // 是最大匹配中的边反向			}
		}
		MEM(vis, 0);
		for (int i = 1; i <= 2 * n; i++) {
			if (!dfn[i]) tarjan(i);
		}
		bool flag = 0;
		for (int i = n + 1; i <= 2 * n; i++) {
			for (int j = head[i]; j != -1; j = edge[j].next) {
				int uu = i, vv = edge[j].v;
				int ui = suo[uu], vi = suo[vv];  // 定义如上所述
				if (pre[uu] == vv && ui != vi) { flag = 1; as[vv] = uu; }
			}
		}
		printf("Heap %d\n", ++X);
		if (!flag) { printf("none\n\n"); continue; }  // 注意判断是否存在
		for (int i = 1; i <= n; i++) if (as[i] - n > 0) printf("(%c,%d) ", i + 'A' - 1, as[i] - n);
		printf("\n\n");
	}
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
08-10
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值