zoukankan      html  css  js  c++  java
  • poj 3041 Asteroids 二分图最小覆盖点

    题意,

      N*N 矩阵, 有些地方有行星, 现有一种武器能够攻击一行, 或者一列,问最少攻击次数.消灭所有行星

    解法.

      因为要消灭所有顶点, 同一行中的顶点能 一次 消灭, 同一列的顶点也能 一次 消灭. 

      我们需要 最小的 攻击次数,  则意味着 最小的攻击次数消灭  所有顶点.  

      将所有存在行星的顶点(x,y), 按x, y轴分别作为 A,B顶点集合,转换成二分图.

      这样 A,B集合连边的代表一次 攻击 箭支 能消灭的行星, 则题目所求就转换成了.

        最小的顶点 覆盖所有边, 既 最小顶点覆盖 问题.

      又因为, ( 在所有图中都满足) 

        最小顶点覆盖 + 最大独立子集 = 顶点数量.

      又 在二分图中 有一下定理 (仅仅在二分图中满足)

        最大匹配数 +  最大独立子集 = 顶点数量

      所以对于本体而言

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

      因为顶点数量最多位 N = 500 个,   所以直接构图,然后用 匈牙利算法就可以了. 当然也可以 用网络流. 如果不嫌麻烦...

      

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    using namespace std;
    
    const int N = 510;
    int ma[N],mb[N];
    int n, k;
    bool g[N][N], vis[N];
    
    bool path( int u ){
        for(int v = 1; v <= n; v++){
            if( g[u][v] && !vis[v] ){
                vis[v] = 1;
                if( ma[v] == -1 || path( ma[v]) ){
                    ma[v] = u; mb[u] = v;
                    return true;    
                }    
            }     
        }    
        return false;
    }
    int main(){
    
        while( scanf("%d%d", &n,&k) != EOF){
            memset( g, 0, sizeof(g));
            int a, b;
            for(int i = 0; i < k; i++){ 
                scanf("%d%d",&a,&b);
                g[a][b] = 1;
            }     
            memset( ma, 0xff, sizeof(ma));
            memset( mb, 0xff, sizeof(mb));
            int res = 0;
            for(int i = 1; i <= n; i++)
            {
                if( mb[i] == - 1){
                    memset( vis, 0, sizeof(vis));
                    res += path(i);    
                }    
            }    
            printf("%d\n", res );
        }
        
        return 0;    
    }
  • 相关阅读:
    颜色透明度16进制对照表
    爬取代理IP
    Python中匹配IP的正则表达式
    IP地址正则表达式的写法
    每日一练 11.23
    每日一练 11.22
    每日一练
    pycharm使用教程
    周总结博客16
    周总结博客15
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/2995828.html
Copyright © 2011-2022 走看看