• POJ3041Asteroids


    转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1299322465

     

    解题思路:

    把方阵看做一个特殊的二分图(以行列分别作为两个顶点集V1V2,其中| V1|=| V2|

    然后把每行x或者每列y看成一个点,而障碍物(x,y)可以看做连接xy的边。按照这种思路构图后。问题就转化成为选择最少的一些点(xy),使得从这些点与所有的边相邻,其实这就是最小点覆盖问题。

     

    再利用二分图最大匹配的König定理:

    最小点覆盖数 = 最大匹配数

     

    PS:最小点覆盖:假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖图的所有的边。)

     

    因此本题自然转化为求 二分图的最大匹配 问题

     

     

    求最大匹配的一种显而易见的算法是:先找出全部匹配,然后保留匹配数最多的。但是这个算法的时间复杂度为边数的指数级函数

    因此,需要寻求一种更加高效的算法——增广路求最大匹配的方法(匈牙利算法)

     

    增广路的定义(也称增广轨或交错轨)

    P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)P上交替出现,则称P为相对于M的一条增广路径。

     

     由增广路的定义可以推出下述三个结论:

      1P的路径个数必定为奇数,第一条边和最后一条边都不属于M

    2、将MP进行取反操作可以得到一个更大的匹配M’

       (反操作:把P中的 匹配边 非匹配边 互换)

    3MG的最大匹配当且仅当不存在M的增广路径P

     

     匈牙利算法轮廓:

      (1)M为空

      (2)找出一条增广路径P,通过异或操作获得更大的匹配M’代替M

    (3)重复(2)操作直到找不出增广路径为止

     

     

     1 //Memory Time 
    2 //464K 47MS
    3
    4 #include<iostream>
    5 using namespace std;
    6
    7 int n,k; //n矩阵规格,k星体数量
    8 int V1,V2; //二分图顶点集
    9 /*矩阵的行列分别属于二分图的两个顶点集V1、V2,其中行x∈V1,列y∈V2*/
    10 bool grid[501][501]; //存储数据方式:可达矩阵
    11 bool vis[501]; //记录V2的点每个点是否已被搜索过
    12 int link[501]; //记录 V2中的点y 在 V1中 所匹配的点x的编号
    13 int m; //最大匹配数
    14
    15 /*Hungary Algorithm*/
    16
    17 bool dfs(int x)
    18 {
    19 for(int y=1;y<=V2;y++)
    20 if(grid[x][y] && !vis[y]) //x到y相邻(有边) 且 节点y未被搜索
    21 {
    22 vis[y]=true; //标记节点y已被搜索
    23 if(link[y]==0 || dfs(link[y])) //link[y]==0 : 如果y不属于前一个匹配M
    24 { //find(link[y] : 如果被y匹配到的节点可以寻找到增广路
    25 link[y]=x; //那么可以更新匹配M'(用M替代M')
    26 return true; //返回匹配成功的标志
    27 }
    28 }
    29 return false; //继续查找V1下一个x的邻接节点
    30 }
    31
    32 void search(void)
    33 {
    34 for(int x=1;x<=V1;x++)
    35 {
    36 memset(vis,false,sizeof(vis)); //清空上次搜索时的标记
    37 if(dfs(x)) //从V1中的节点x开始寻找增广路
    38 m++;
    39 }
    40 return;
    41 }
    42
    43 int main(void)
    44 {
    45 cin>>n>>k;
    46 V1=V2=n;
    47
    48 int x,y; //坐标(临时变量)
    49 for(int i=1;i<=k;i++)
    50 {
    51 cin>>x>>y;
    52 grid[x][y]=true; //相邻节点标记
    53 }
    54
    55 /*增广轨搜索*/
    56
    57 search();
    58
    59 /*Output*/
    60
    61 cout<<m<<endl;
    62
    63 return 0;
    64 }

  • 相关阅读:
    连接Oracle时报错ORA-12541: TNS: 无监听程序
    DevExpress中的GridControl控件设置了列Readonly后,想双击弹出明细的实现
    根据现有的XML文件生成其对应的实体类
    SQL Server Profiler的简单使用
    给视图增加索引,提高多表关联数据查询效率
    您对无法重新创建的表进行了更改或者启用了“阻止保存要求重新创建表的更改”选项
    卸载win10内置的onenote
    XmlSerializer 实现序列化CDATA
    sqlserver数据库不能重命名报错5030
    智力题
  • 原文地址:https://www.cnblogs.com/lyy289065406/p/2121730.html
Copyright © 2020-2023  润新知