二分图必须边--poj1486

来源:互联网 发布:unity3d 2d游戏教程 编辑:程序博客网 时间:2024/06/05 19:07

Language:
Sorting Slides
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 2918 Accepted: 1121

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

46 22 10 204 18 6 168 20 2 1810 24 4 89 1519 1711 721 1120 2 0 20 2 0 21 11 10

Sample Output

Heap 1(A,4) (B,1) (C,2) (D,3)Heap 2none第一次听说“二分图必须边”这个名词求二分匹配的必须边,即x集合中的某个点最多只能和y集合中的某个点唯一匹配,那么这条边就叫做二分匹配的必须边,那我们可以先求出最大匹配,然后枚举每条边,将其删除,之后将两个点中其中一个进行匹配,若匹配成功,则说明该边不是必须边,若不能进行匹配则输出这条匹配边后回复删除的那条边。

要判断一条边是否为二分图中必须边,方法如下:

1、先求出原图的任意最大匹配

2、对二分图某一边的所有点,删去其当前的匹配边。删的过程不是简单的将原图设为不连通,你还得将其相应的匹配值设为未匹配。

假如原图link[a]=b;  那我们删边的时候既要讲map[b][a]设为0.,同时也要讲link[a]设为-1。(举个例子而已,数据的写法自己定)

3、对此跟新图再次从b点(承接上面的例子)进行一次最大匹配,如果此时还能完成最大匹配,那么刚才删去的那条边显然就不是必须边了。反之,必须边成立!(做完记得将图还原)

4、重复2步骤,直到所有的点都被删过了一次当前匹配边

(还有一个问题就是,再对跟新图进行最大匹配验证的过程中,这必然不可避免的会改变其他匹配边原来的信息。比如a点原来匹配着b点,在新方案中,它可能却变成了匹配c点。其实这对我们的算法没有任何影响,因为我们本来的目的就只是对点进行匹配,至于该点和那个点匹配,无所谓。最开始,我们也是任意的进行了一次二分匹配。我们删边的目的只是为了验证该点是不是还存在着其他匹配方案,至于是从哪一个方案变到哪一个方案,没有任何关系)

#include<iostream>#include<cstring>#include<cstdio>using namespace std;struct bian{    int x1,x2,y1,y2;} a[30];int grid[30][30];bool vis[30];int pre[30];int n;bool dfs(int u){    for(int i=1; i<=n; i++)    {        if(!vis[i]&&grid[u][i])        {            vis[i]=1;            if(pre[i]==0||dfs(pre[i]))            {                pre[i]=u;                return 1;            }        }    }    return 0;}int main(){    //freopen("in.txt","r",stdin);    int x,y;    int loop=1;    while(cin>>n,n)    {        memset(grid,0,sizeof(grid));        memset(pre,0,sizeof(pre));        for(int i=1; i<=n; i++)            cin>>a[i].x1>>a[i].x2>>a[i].y1>>a[i].y2;        for(int i=1; i<=n; i++)        {            cin>>x>>y;            for(int j=1; j<=n; j++)                if(x>a[j].x1&&x<a[j].x2&&y>a[j].y1&&y<a[j].y2)                    grid[i][j]=1;        }        int ans=0;        for(int i=1; i<=n; i++)        {            memset(vis,0,sizeof(vis));            if(dfs(i))                ans++;        }        int num=0;        int first=0;        cout<<"Heap "<<loop++<<endl;        for(int i=1; i<=n; i++)        {            ans=pre[i];//枚举删除边            pre[i]=0;            grid[ans][i]=0;            memset(vis,0,sizeof(vis));            if(!dfs(ans))            {                if(first)                    cout<<' ';                else                    first=1;                cout<<"("<<char('A'+i-1)<<","<<ans<<")";                pre[i]=ans;            }            grid[ans][i]=1;//恢复改变的状态        }        if(!first)            cout<<"none";        cout<<endl<<endl;    }    return 0;}





原创粉丝点击