码迷,mamicode.com
首页 > 其他好文 > 详细

poj 1486(二分图必须边)

时间:2015-05-18 09:02:16      阅读:110      评论:0      收藏:0      [点我收藏+]

标签:

题意:有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;
}

poj 1486(二分图必须边)

标签:

原文地址:http://blog.csdn.net/hyczms/article/details/45804119

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!