列表

详情


NC51318. 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.

输入描述

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.

输出描述

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.

示例1

输入:

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

输出:

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

Heap 2
none

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 3ms, 内存消耗: 384K, 提交时间: 2022-08-31 21:37:12

#include<bits/stdc++.h>
using namespace std;
int link[30],rlink[30],n;
bool g[30][30],chk[30];
bool findpath(int x)
{
    for(int y=0;y<n;y++)
    {
        if(g[x][y]&&!chk[y])
        {
            chk[y]=true;
            if(rlink[y]==-1||findpath(rlink[y]))
            {
                rlink[y]=x;
                link[x]=y;
                return true;
            }
        }
    }
    return false;
}
int maxmatch()
{
    memset(link,-1,sizeof(link));
    memset(rlink,-1,sizeof(rlink));
    int ret=0;
    for(int x=0;x<n;x++)
    {
        memset(chk,false,sizeof(chk));
        if(findpath(x))
            ret++;
    }
    return ret;
}
struct Rec
{
    int minx,maxx,miny,maxy;
};
Rec rec[30];
int main()
{
    int ca=0;
    while(scanf("%d",&n)&&n)
    {
        if(ca)
            printf("\n");
        memset(g,false,sizeof(g));
        for(int i=0;i<n;i++)
            scanf("%d%d%d%d",&rec[i].minx,&rec[i].maxx,&rec[i].miny,&rec[i].maxy);
        for(int i=0;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            for(int j=0;j<n;j++)
            {
                if(x>=rec[j].minx&&x<=rec[j].maxx&&y>=rec[j].miny&&y<=rec[j].maxy)
                {
                    g[j][i]=true;
                }
            }
        }
        maxmatch();
        printf("Heap %d\n",++ca);
        bool flag=true,ths;
        for(int i=0;i<n;i++)
        {
            int t=link[i],rl;
            ths=true;
            for(int j=0;j<n;j++)
            {
                if(t!=j&&g[i][j])
                {
                    rl=rlink[j];
                    link[rl]=-1;
                    rlink[j]=i;
                    link[i]=j;
                    rlink[t]=-1;
                    memset(chk,false,sizeof(chk));
                    chk[j]=true;
                    if(findpath(rl))
                    {
                        ths=false;
                        break;
                    }
                    rlink[j]=rl;
                    link[rl]=j;
                    link[i]=t;
                    rlink[t]=i;
                }
            }
            if(ths)
            {
                if(!flag)
                    printf(" ");
                flag=false;
                printf("(%c,%d)",'A'+i,link[i]+1);
            }
        }
        if(flag)
            printf("none");
        printf("\n");
    }
    return 0;
}

C++14(g++5.4) 解法, 执行用时: 3ms, 内存消耗: 208K, 提交时间: 2019-11-30 20:01:20

#include<cstdio>
#include<cstring>
using namespace std;
#define N 27
int vis[N],match[N],ans[N],x1[N],x2[N],y1[N],y2[N],n,T;
bool g[N][N],flag;
 
inline bool dfs(int x) {
    for (register int i=1; i<=n; i++)
        if (!vis[i] && g[x][i]) {
            vis[i]=1;
            if (!ans[i] || dfs(ans[i])) {
                ans[i]=x;//第 i 个幻灯片对应数字为 x
                return true;
            }
        }
    return false;
}
 
inline int find() {//求二分图最大匹配
    int sum=0;
    memset(ans,0,sizeof ans);
    for (register int x=1; x<=n; x++){
            memset(vis,0,sizeof vis);
            if (dfs(x)) sum++;// 总匹配数
    }
    return sum;
}
 
int main() {
    while(~scanf("%d",&n) && n) {
        if (T) puts("");
        printf("Heap %d\n",++T);
        memset(g,0,sizeof g);
 
        for (int i=1; i<=n; i++)
            scanf("%d%d%d%d",&x1[i],&x2[i],&y1[i],&y2[i]);
            
        for (int i=1,x,y; i<=n; i++) {
            scanf("%d%d",&x,&y);
            for (int j=1; j<=n; j++)
                if (x>=x1[j] && x<=x2[j] && y>=y1[j] && y<=y2[j])
                    g[i][j]=1;//如果数字在幻灯片范围之内的话则连边,有机会匹配
        }
 
        int tot=find(),flag=0;
        
                //接下来我们要去除这种情况
         
        for (int j=1; j<=n; j++)
            for (int i=1;i<=n; i++)
                if (g[i][j]) {
                    g[i][j]=0;//考虑依次删去每条边,如果有唯一对应,那么至少有一边删去后使匹配数减少
                    if (find()!=tot) {
                        if (flag) printf(" ");
                        else flag=1;
                        printf("(%c,%d)",j-1+'A',i);//如果幻灯片 j 与 数字 i 是唯一搭配,直接输出
                    }
                    g[i][j]=1;
                }
        if (!flag) printf("none");//如果删去任意一边匹配数都不变,则对应不唯一
        puts("");//相当于printf("\n");
    }
    return 0;
}

上一题