ZOJ-1197-Sorting Slides【二分图匹配】【拓扑排序】

来源:互联网 发布:淘宝350客户端下载 编辑:程序博客网 时间:2024/06/06 01:31

ZOJ-1197-Sorting Slides


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

题目链接:ZOJ-1197

题目大意:这道题,题目意思比较坑。

1.给出n个矩形和n个点,进行配对(点在矩形内部则配对成功),2.给出数据初始一定是能配对上的,即所有的点都能对应上一个矩阵(完美匹配)3.问:是否存在一个匹配,删去该匹配,无法构成完美匹配

注意:构成完美匹配必须边(唯一边)则输出,如果不存在必须边则输出“none”

题目思路:可以看出这是道二分图匹配。

1.加边,因为点很少(最多26),直接用矩阵存储2.遍历每条边,删除该边,跑一遍二分图,如果不能完美匹配,则该条边是必须边

参考博客:here

样例:

510 40 40 7020 50 30 6030 60 20 5045 70 10 4045 70 10 4025 5535 5535 4555 2565 25          //答案: Heap 1 (C,3)

以下是代码:

#include <iostream>#include <iomanip>#include <fstream>#include <sstream>#include <cmath>#include <cstdio>#include <cstring>#include <cctype>#include <algorithm>#include <functional>#include <numeric>#include <string>#include <set>#include <map>#include <stack>#include <vector>#include <queue>#include <deque>#include <list>using namespace std;int edge[50][50];int used[50];int matchx[50];int n,cnt;bool dfs(int k){    for(int i=0;i<n;i++){        if(edge[k][i]&&!used[i]){            used[i]=1;            if(matchx[i]==-1 || dfs(matchx[i])){                matchx[i]=k;                return true;            }        }    }    return false;}int hungry(){    cnt=0;    memset(matchx,-1,sizeof(matchx));    for(int i=0;i<n;i++){        memset(used,0,sizeof(used));        if(dfs(i)){            cnt++;        }    }    return cnt;}struct node{    int xmin, xmax, ymin, ymax;}rect[1005];int main(){    int cas = 0;    while( cin >> n ){        if (n == 0) break;        memset(edge, 0, sizeof (edge));        for( int i=0 ; i<n ; i++ )        {            scanf("%d%d%d%d", &rect[i].xmin, &rect[i].xmax, &rect[i].ymin, &rect[i].ymax);        }        for( int i=0 ; i<n ; i++ )        {            int x, y;            scanf("%d%d", &x, &y);            for( int j=0 ; j<n ; j++ )            {                if(x<=rect[j].xmax && x>=rect[j].xmin && y<=rect[j].ymax && y>=rect[j].ymin)                {                    edge[j][i] = 1;                }            }        }        printf("Heap %d\n", ++cas);        int flag = 0;        for (int i = 0; i < n; i++)        {            for (int j = 0; j < n; j++)            {                if (edge[i][j] == 0) continue;                edge[i][j] = 0;                if (hungry() < n)                {                    if (flag == 0) printf("(%c,%d)",'A'+ i, j + 1);                    else printf(" (%c,%d)",'A'+ i, j + 1);                    flag = 1;                }                edge[i][j] = 1;            }        }        if (!flag) cout << "none";        cout << endl << endl;    }    return 0;}

另外给出拓扑排序的做法

#include <iostream>#include <iomanip>#include <fstream>#include <sstream>#include <cmath>#include <cstdio>#include <cstring>#include <cctype>#include <algorithm>#include <functional>#include <numeric>#include <string>#include <set>#include <map>#include <stack>#include <vector>#include <queue>#include <deque>#include <list>using namespace std;struct node{    int xmin, xmax, ymin, ymax;}rect[1005];set<int> a[2010];queue<int> q;bool vis[1005];int ans[2010];int num = 0;int main(){    int n;    int cas = 0;    while (cin >> n, n){        for (int i = 0; i<n * 2; i++) a[i].clear();        memset(ans, -1, sizeof(ans));        num = 0;        memset(vis, 0, sizeof(vis));        while (!q.empty()) q.pop();        for (int i = 0; i<n; i++){            scanf("%d%d%d%d", &rect[i].xmin, &rect[i].xmax, &rect[i].ymin, &rect[i].ymax);        }        for (int i = 0; i<n; i++){            int x, y;            scanf("%d%d", &x, &y);            for (int j = 0; j<n; j++){                if (x <= rect[j].xmax&&x >= rect[j].xmin&&y <= rect[j].ymax&&y >= rect[j].ymin){                    a[j].insert(n + i);                    a[i + n].insert(j);                }            }        }        for (int i = 0; i<2 * n; i++){            if (a[i].size() == 1){                q.push(i);            }        }        while (!q.empty()){            int tp = q.front();            q.pop();            if (vis[tp]) continue;            vis[tp] = 1;            //if( a[tp].size()==0 ) continue;            int son = *a[tp].begin();            vis[son] = 1;            ans[tp] = son;            ans[son] = tp;            num++;            for (set<int>::iterator i = a[son].begin(); i != a[son].end(); i++){                int nxt = *i;                a[nxt].erase(a[nxt].find(son));                if (a[nxt].size() == 1){                    q.push(nxt);                }            }        }        printf("Heap %d\n", ++cas);        if (num){            int fir = 1;            for (int i = 0; i<n; i++){                if (ans[i]==-1) continue;                if (fir) printf("(%c,%d)", 'A' + i, ans[i] - n + 1);                else printf(" (%c,%d)", 'A' + i, ans[i] - n + 1);                fir = 0;            }            puts("");        }        else{            puts("none");        }        puts("");    }    return 0;}
0 0
原创粉丝点击