zoukankan      html  css  js  c++  java
  • POJ 1486二分图的必要边

    题意:有n个大小不等透明的幻灯片(只有轮廓和上面的数字可见)A、B、C、D、E…按顺序叠放在一起,现在知道每个幻灯片大小,由于幻灯片是透明的,所以能看到幻灯片上的数字(给出了每个数字的坐标,但不知道这些数字分别属于哪个幻灯片),现在要你根据当前的已知信息,输出能够确定的幻灯片 编号和数字的匹配。

    英语太差。一直坑在这句话 = =


    将点和图进行匹配,求出最大匹配,再进行删边匹配,若匹配数不再为n,则说明这条边为必要边,输出。

    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
    

      

    output

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

      

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    bool used[1010];
    int p[1010];
    bool MAP[1010][1010];
    int q[1010];
    int X[1010][2];
    int Y[1010][2];
    int flag;
    int num,n,m;
    bool work(int c)
    {
        for(int i = 1; i <= n; i++)
        {
            if(!used[i] && MAP[c][i])
            {
                used[i] = true;
                if(p[i]==-1 || work(p[i]))
                {
                    p[i] = c;
                   return true;
                }
            }
        }
        return false;
    }
    
    void sol()
    {
        num=0;
        memset(p,-1,sizeof(p));
        for(int i = 1; i <= n; i++)
        {
            memset(used,0,sizeof(used));
            if(work(i))
                num++;
        }
    }
    
    
    int main()
    {
        int cas = 1;
        while(~scanf("%d",&n) && n)
        {
            memset(MAP,false,sizeof(MAP));
            for(int i = 1; i <= n; i++)
                scanf("%d%d%d%d",&X[i][0],&X[i][1],&Y[i][0],&Y[i][1]);
            int a,b;
            for(int i = 1; i <= n; i++)
            {
                scanf("%d%d",&a,&b);
                for(int j = 1; j <= n; j++)
                {
                    if(a > X[j][0] && a < X[j][1] && b > Y[j][0] && b< Y[j][1])
                        MAP[i][j] = true;
                }
            }
            sol();
            printf("Heap %d
    ", cas++);
            flag = 0;
            if(num == n)
            {
                for(int i = 1; i <= n; i++)
                    q[i] = p[i];
    
                for(int i = 1; i <= n; i++)
                {
                    MAP[q[i]][i] = false;         //删边
                    sol();
                    if(num == n)                  //判断是非为必要边
                    {
                        continue;
                    }
                    else
                    {
                        if(flag)
                            printf(" ");
                        printf("(%c,%d)",'A'-1+i,q[i]);
                        flag = 1;
                    }
                    MAP[q[i]][i] = true;         //还原
                }
            }
            if(!flag)
                printf("none");
            printf("
    
    ");
        }
        return 0;
    }
     
    

      

  • 相关阅读:
    简单了解winform
    SqL语句基础之增删改查
    数据库之表
    数据库基本概念与操作
    搞死人不偿命的 Bank系统
    for的循环题
    .net framework 版本汇总
    LinqToEntity模糊查询的方法选择
    日常工作中的点滴:C# 根据字节长度截包含中文的字符串
    64位系统 IIS中应用程序池设置导致 访问数据库错误
  • 原文地址:https://www.cnblogs.com/Przz/p/5409846.html
Copyright © 2011-2022 走看看