POJ 1486 Sorting Slides(寻找必须边)

题意:找出幻灯片与编号唯一对应的情况

思路: 1:求最大匹配,若小于n,则答案为none,否则转2   

    (不过我代码没有事先判断一开始的最大匹配数是否<n,但这样也过了,估计给的数据最大匹配数一定为n吧)

   2:删除一条边e,以e的一个端点找增广路,若不能找到增广路则e是必须边   

    也就是重新计算匹配数,如果匹配数减少说明此边是必须也是唯一的.    如果一样说明这边存不存在都行.转3

   3:恢复原图,继续步骤2,直到每条边都被删除过

刚开始看网上别人的代码,有一点看不懂,那就是为什么只要找到唯一对应的就输出。

而不是最后当确定所有的幻灯片都唯一确定后再一起输出,否则只要有一个不唯一确定就输出"none" 。

后来网上查了查,发现:只要能推出多少唯一对应的,就唯一显示多少,只有全部不能推出来才显示“none”!!!!!!!!!! 坑死我了啊!

举个例子:

5

10 40 40 70

20 50 30 60

30 60 20 50

45 70 10 40

45 70 10 40

25 55

35 55

35 45

55 25

65 25           答案: Heap 1 (C,3)

 

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>

using namespace std;

int n,cnt;
bool flag;
int edge[50][50];  //edge[i][j]表示j点在第i张幻灯片里
int used[50];
int matchx[50];

struct Slide{
    int xmin,xmax,ymin,ymax;
}slide[50];

struct Num{
    int x,y;
}num[50] ;

void deal(){
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if((slide[i].xmin<=num[j].x)&&(num[j].x<=slide[i].xmax)&&(slide[i].ymin<=num[j].y)&&(num[j].y<=slide[i].ymax))
                edge[i][j]=1;
        }
    }
}

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;
}

int main()
{
    int cases=0;
    while(scanf("%d",&n)!=EOF){
        if(n==0)
            break;
        memset(edge,0,sizeof(edge));

        flag=false;
        cases++;

        for(int i=0;i<n;i++){
            scanf("%d%d%d%d",&slide[i].xmin,&slide[i].xmax,&slide[i].ymin,&slide[i].ymax);
        }
        for(int i=0;i<n;i++){
            scanf("%d%d",&num[i].x,&num[i].y);
        }

        deal();

        printf("Heap %d\n",cases);
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    if(edge[i][j]==0)
                        continue;
                    edge[i][j]=0;
                    //如果删去边(i,j),匹配数减少,说明是必须边。
                    if(hungry()<n){
                        flag=true;
                        char ch='A'+i;
                        printf("(%c,%d) ",ch,j+1);
                    }
                    edge[i][j]=1;
                }
            }


        if(!flag){
            printf("none\n\n");
        }
        else{
            printf("\n\n");
        }
    }
    return 0;
}

 

 

posted @ 2013-08-26 10:23  辰曦~文若  阅读(407)  评论(0编辑  收藏  举报