• Antenna Placement POJ


    题意:图没什么用  给出一个地图 地图上有 点 一次可以覆盖2个连续 的点( 左右 或者 上下表示连续)问最少几条边可以使得每个点都被覆盖

    最小路径覆盖       最小路径覆盖=|G|-最大匹配数                   证明:https://blog.csdn.net/qq_34564984/article/details/52778763

    证明总的来说就是尽可能多得连边 边越多 可以打包一起处理得点就越多(这里题中打包指连续得两个点只需要一条线段就能覆盖)

    拆点思想   :匈牙利拆了点才好写  不然十分麻烦  简单地说就是点复制一遍  从一边开始匹配   

    建图:X如果需要覆盖  和它上下左右需要覆盖的点连边  当然这里是和拆完点的另外一个部分的点连边  amp[x][y]两维 分别表示两个集合  

    答案   最小路径覆盖 = 顶点数 – 最大二分匹配数/2  为什么要除以2呢,因为拆点复制了一遍 需要除回去  比如 

    1 2 有变 变成

    1 和2'  

    2 和 1'形成了匹配   这样匹配就加倍了 所以除以2就好

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    const int maxn=3000;
    char mp[maxn][maxn];
    int  amp[maxn][maxn];
    int vis[maxn];
    int Hash[maxn][maxn];
    int cnt=0;
    int ans=0;
    int link[maxn];
    int dx[]={
        1,-1,0,0
    };
    int dy[]={
        0,0,-1,1
    };
    bool dfs(int x){
        for(int i=1;i<=cnt;i++){
            if(amp[x][i]&&!vis[i]){
                vis[i]=1;
                if(link[i]==0||dfs(link[i])){
                    link[i]=x;
                    return 1;
                }
            }
        }
        return 0;
    }
    void solve(){
     ans=0;
     memset(link,0,sizeof(link));
        for(int i=1;i<=cnt;i++){
            memset(vis,0,sizeof(vis));
            if(dfs(i))ans++;
        }
    }
    int main(){
        int t;
        
        cin>>t;
        while(t--){
            int n,m;
            cnt=0;
            memset(amp,0,sizeof(amp));
            cin>>n>>m;
            for(int i=1;i<=n;i++)scanf("%s",mp[i]+1);
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    if(mp[i][j]=='*') Hash[i][j]=++cnt;
                }
            }
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    if(mp[i][j]=='*'){
                        for(int k=0;k<4;k++){
                            int tx=i+dx[k],ty=j+dy[k];
                            if(mp[tx][ty]=='*')amp[Hash[i][j]][Hash[tx][ty]]=1;
                        }
                    }
                }
            }
         solve();
         cout<<cnt-ans/2<<endl;
        }
    
        return 0;
    }
  • 相关阅读:
    Python的词法分析与语法分析
    使用svn log确定分支创建的时间点
    Python的作用域
    SVN的版本日期
    理解SVN关键词BASE,HEAD,COMMITTED,PREV
    SVN的属性
    EL表达式 (详解)
    java jsp el fn
    java防止表单重复提交
    数据库的事务处理
  • 原文地址:https://www.cnblogs.com/ttttttttrx/p/10014125.html
Copyright © 2020-2023  润新知