zoukankan      html  css  js  c++  java
  • poj3020 Antenna Placement 二分匹配之最小路径覆盖

           题目的意思大致就是,一个矩形中,有N个城市,现在这n个城市都要覆盖无线,若放置一个基站,那么它至多可以覆盖相邻的两个城市。
    问至少放置多少个基站才能使得所有的城市都覆盖无线?
    构图:行扫描所有城市,编号,如果有城市相邻就连一条边,当然如果3和4相邻,首先graph[3][4]=1,当扫描到4时graph[4][3]也连一条边,最后只需要取一半即可.求最大匹配的一半,这样可以得到所有2个相邻城市被一个基站覆盖所需要的基站数。然后再加上独立的那些基站即可。
    公式是:N-最大匹配(代表所有可以和相邻城市配对的城市数)+最大匹配/2=N-最大匹配/2;

    Source Code

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
        int nx, ny;             // X的點數目、Y的點數目
    int mx[405], my[405];   // X各點的配對對象、Y各點的配對對象
    bool vy[405];           // 紀錄Graph Traversal拜訪過的點
    bool adj[405][405];     // 精簡過的adjacency matrix
    int xx,n,m,cc[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    char g[41][11];
    // 以DFS建立一棵交錯樹
    bool DFS(int x)
    {
        for (int y=0; y<ny; ++y)
            if (adj[x][y] && !vy[y])
            {
                vy[y] = true;

                // 找到擴充路徑
                    if (my[y] == -1 || DFS(my[y]))
                {
                    mx[x] = y; my[y] = x;
                    return true;
                   }
            }
        return false;
    }

    int bipartite_matching()
    {
        // 全部的點初始化為未匹配點。
        memset(mx, -1, sizeof(mx));
            memset(my, -1, sizeof(my));

        // 依序把X中的每一個點作為擴充路徑的端點,
        // 並嘗試尋找擴充路徑。
        int c = 0;
        for (int x=0; x<nx; ++x)
    //     if (mx[x] == -1)    // x為未匹配點,這行可精簡。
            {
                // 開始Graph Traversal
                memset(vy, false, sizeof(vy));
                if (DFS(x)) c++;
            }
        return c;
    }
      void  ini()
    {
             int a,b;
             xx=0;
             for(int i=0;i<n;i++)
             for(int j=0;j<m;j++)
             {
               if(g[i][j]=='*')
               {
                xx++;
                a=i*m+j;
                for(int h=0;h<4;h++)
                {
                        if(i+cc[h][0]>=0&&i+cc[h][0]<n&&j+cc[h][1]>=0&&j+cc[h][1]<m&&g[i+cc[h][0]][j+cc[h][1]]=='*')
                        {
                          b=(i+cc[h][0])*m+j+cc[h][1];
                          adj[a][b]=1;
                        }
                }
               }
             }
             nx=ny=m*n;
       }
               
              
    main()
    {
              int t,i;
             scanf("%d",&t);
             while(t--)
             {
               scanf("%d%d",&n,&m);
               memset(adj, 0, sizeof(adj));
               getchar();
               for(i=0;i<n;i++)
                  gets(g[i]);
               ini();
              
               printf("%d\n",xx-bipartite_matching()/2);
             }      
              system("pause");
       }

     
  • 相关阅读:
    一些技术摘选及随想
    新技术学习方法如何学习一门新编程语言(Lua)?
    什么时候该用ASSERT?
    MFC是否过时?如何学习MFC?
    Windows桌面开发者的必备软件
    Comet技术选择,论Is node.js best for Comet?
    关于C/C++内存管理一些乱讲
    debug
    C语言趣味题目
    CSS之简单的双引号
  • 原文地址:https://www.cnblogs.com/zxj015/p/2740296.html
Copyright © 2011-2022 走看看