最大二分匹配 ZQUOJ21474 && POJ1486 Sorting Slides

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

题目大意: 这道题的意思是一些大小不等透明的幻灯片(只有轮廓和上面的数字可见)ABCDE…按顺序叠放在一起,现在知道每个幻灯片左上角和右下角的坐标,并且由于幻灯片是透明的,所以能看到幻灯片上的数字(给出了每个数字的坐标,但不知道这些数字分别属于哪个幻灯片),现在要你根据当前的已知信息,输出能够确定的幻灯片编号和数字的匹配,例如(A,4) (B,1) (C,2) (D,3);
题目分析:如果建立二分匹配的模型来做,那么也就是说这些边是二分匹配的必须边,删掉这些边后,匹配就会不成功。因此给出了一种做法:这道题要先计算出最大匹配数,并把最大匹配表记录下来,然后把匹配到的边记录在队列里,然后依次删除,重新计算匹配数,如果匹配数减少说明此边是必须也是唯一的.如果一样说明这边存不存在都行,要从原来记录的最大匹配表中减掉此边.

AC代码:
View Code
 1 #include<stdio.h>
 2 #include<string.h>
 3 typedef struct
 4 {
 5     int x1,x2,y1,y2;
 6 }Rectangle;
 7 Rectangle slide[27];     //幻灯片
 8 int n,map[27][27],vis[27],match[27],path[27];   //map幻灯片和编号之间的边,match记录与幻灯片匹配的编号,vis标记幻灯片是否访问过,path路径
 9 int dfs(int v)     //找增广路径
10 {
11     int i;
12     for(i=1;i<=n;i++)
13     {
14         if(!vis[i]&&map[v][i])
15         {
16             vis[i]=1;
17             if(!match[i]||dfs(match[i]))
18             {
19                 match[i]=v;
20                 return 1;
21             }
22         }
23     }
24     return 0;
25 }
26 int max_match()      //匈牙利算法
27 {
28     int i,count=0;
29     memset(match,0,sizeof(match));
30     for(i=1;i<=n;i++)
31     {
32         memset(vis,0,sizeof(vis));
33         if(dfs(i))
34             count++;
35     }
36     return count;
37 }
38 int main()
39 {
40     int t=1,i,j,x,y,num,flag;
41     while(scanf("%d",&n)&&n)
42     {
43         for(i=1;i<=n;i++)
44             scanf("%d%d%d%d",&slide[i].x1,&slide[i].x2,&slide[i].y1,&slide[i].y2);
45         memset(map,0,sizeof(map));
46         for(i=1;i<=n;i++)
47         {
48             scanf("%d%d",&x,&y);
49             for(j=1;j<=n;j++)   //编号被幻灯片上覆盖的,编号跟其连边,表示该编号可能在该幻灯片上
50                 if(x>=slide[j].x1&&x<=slide[j].x2&&y>=slide[j].y1&&y<=slide[j].y2)
51                     map[i][j]=1;
52         }
53         num=max_match();
54         flag=0;
55         printf("Heap %d\n",t++);
56         if(num==n)  //能找到一种方案让每个编号对应一个幻灯片
57         {
58             for(i=1;i<=n;i++)
59                 path[i]=match[i];
60             for(i=1;i<=n;i++)
61             {
62                 map[path[i]][i]=0;  //删边
63                 if(max_match()!=num) //如果不能再次达到最大匹配,则编号与幻灯片时唯一的
64                 {
65                     if(flag)
66                         printf(" ");
67                     printf("(%c,%d)",i+'A'-1,path[i]);    //输出
68                     flag=1;
69                     map[path[i]][i]=1;
70                 }
71             }
72         }
73         if(!flag)
74             printf("none");
75         printf("\n\n");
76     }
77     return 0;
78 }
 



原文地址:https://www.cnblogs.com/frog112111/p/2623947.html