zoukankan      html  css  js  c++  java
  • 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
    ",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
    
    ");
            }
            else{
                printf("
    
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    聊聊 print 的前世今生
    在树莓派里搭建 Lighttpd 服务器
    如何重复执行一条命令直至运行成功?
    手把手教你Windows Linux双系统的安装与卸载
    你以为只有马云会灌鸡汤?Linux 命令行也会!
    Linux 下三种提高工作效率的文件处理技巧
    太高效了!玩了这么久的Linux,居然不知道这7个终端快捷键!
    Linux下分析bin文件的10种方法
    Linux下几个与磁盘空间和文件尺寸相关的命令
    如何让你的脚本可以在任意地方都可执行?
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3282047.html
Copyright © 2011-2022 走看看