题意:有n张幻灯片重叠在一起,给出了每张矩形幻灯片在坐标系上的范围大小,然后给出了n个页码在坐标系的位置,因为幻灯片都是透明的所以无法确定页码是在哪个幻灯片上,需要判断有哪些幻灯片的页码可以确定,幻灯片给出的顺序是A…,页码给出的顺序是1…。
题解:先建图,幻灯片是一个集合,页码是另一个集合,页码a在幻灯片b内部可以连一条边,然后先进行二分图匹配找到最大匹配数,然后枚举每一条边,如果删除这条边再进行以此二分图匹配,这时得到的最大匹配数如果和之前的不相等(页码可以有其他的幻灯片匹配),说明这条边是必须的(也就是解),否则这条边不确定。
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
const int N = 105;
struct Sli {
int xmin, xmax, ymin, ymax;
}sli[N];
int n, vis[N], link[N], x[N], y[N], g[N][N];
bool dfs(int u) {
for (int i = 0; i < n; i++) {
if (!vis[i] && g[u][i]) {
vis[i] = 1;
if (link[i] == -1 || dfs(link[i])) {
link[i] = u;
return true;
}
}
}
return false;
}
int hungray() {
memset(link, -1, sizeof(link));
int res = 0;
for (int i = 0; i < n; i++) {
memset(vis, 0, sizeof(vis));
if (dfs(i))
res++;
}
return res;
}
int main() {
int cas = 1;
while (scanf("%d", &n) && n) {
memset(g, 0, sizeof(g));
printf("Heap %d\n", cas++);
for (int i = 0; i < n; i++)
scanf("%d%d%d%d", &sli[i].xmin, &sli[i].xmax, &sli[i].ymin, &sli[i].ymax);
for (int i = 0; i < n; i++)
scanf("%d%d", &x[i], &y[i]);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
if (x[j] >= sli[i].xmin && x[j] <= sli[i].xmax && y[j] >= sli[i].ymin && y[j] <= sli[i].ymax)
g[i][j] = 1;
}
int res = hungray(), flag = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
if (g[i][j]) {
g[i][j] = 0;
int temp = hungray();
if (temp < res) {
if (!flag)
flag = 1;
else
printf(" ");
printf("(%c,%d)", ‘A‘ + i, j + 1);
}
g[i][j] = 1;
}
}
if (!flag)
printf("none");
printf("\n\n");
}
return 0;
}
时间: 2024-11-07 13:16:10