zoukankan      html  css  js  c++  java
  • 二分图最大匹配 hdoj 1045

    题目:hdoj1045


    题意:给出一个图。当中有 . 和 X 两种,. 为通路,X表示墙,在当中放炸弹,然后炸弹不能穿过墙。问你最多在图中能够放多少个炸弹?


    分析:这道题目是在上海邀请赛的题目的数据简化版。数据水了,所以有非常多方法,这里讲二分图最大匹配,题目难点在于建图

    想到用暴力过。可是事实证明我想多了。

    然后又想到多重二分匹配,后来发现没有办法表示图中的行列中墙的阻隔,后来看了别人的建图,瞬间认为高大上。

    建图,首先把每一行中的能够放一个炸弹的一块区域标记为同一个数字。数字不反复,然后列做同样的处理,即缩点。

    缩点之后原图矩阵中每一个点都对用一个行数字和一个列数字,然后依照这两个数字进行二分匹配,其同样值仅仅取一个,得到的结果就是ans;

    注意:每次推断增广的时候首先检查一下当前点有没有匹配。假设匹配就不用搜索,由于有多个值相应一个点,所以...


    代码:

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int N = 10;
    #define Del(x,y) memset(x,y,sizeof(x))
    char map[N][N];
    int path[N][N];
    int line[N][N],row[N][N],link[N],vis[N],vlink[N];
    int n,cnt_row,cnt_line;
    bool dfs(int x)
    {
        for(int i=0;i<cnt_line;i++)
        {
            if(path[x][i]==1 && vis[i]==0)
            {
                vis[i]=1;
                if(link[i]==-1 || dfs(link[i]))
                {
                    link[i]=x;
                    vlink[x]=i;
                    return true;
                }
            }
        }
        return false;
    }
    void solve()
    {
        int ans=0;
        Del(link,-1);
        Del(vlink,-1);
        for(int i=0;i<cnt_row;i++)
        {
            if(vlink[i]==-1){  ///注意!标记找过的
                Del(vis,0);
                if(dfs(i))
                    ans++;
            }
        }
        printf("%d
    ",ans);
    }
    int main()
    {
        //freopen("Input.txt","r",stdin);
        while(~scanf("%d",&n) && n)
        {
            char c;
            Del(map,0);
            for(int i=0;i<n;i++)
            {
                getchar();
                for(int j=0;j<n;j++)
                    scanf("%c",&map[i][j]);
            }
            Del(line,-1);
            Del(row,-1);
            cnt_row=0,cnt_line=0;
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<n;j++)
                {
                    if(map[i][j] == '.' && row[i][j] == -1)
                    {
                        for(int k = j; map[i][k] == '.' && k < n; ++k)
                            row[i][k] = cnt_row;
                        cnt_row++;
                    }
                    if(map[j][i] == '.' && line[j][i] == -1)
                    {
                        for(int k = j; map[k][i] == '.' && k < n; ++k)
                            line[k][i] = cnt_line;
                        cnt_line++;
                    }
                }
            }
            Del(path,0);
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<n;j++)
                {
                    if(map[i][j]=='.')
                        path[row[i][j]][line[i][j]]=1;
                }
            }
            solve();
        }
        return 0;
    }
    


  • 相关阅读:
    [转]javaweb学习总结(二十二)——基于Servlet+JSP+JavaBean开发模式的用户登录注册
    [转]javaweb学习总结(二十一)——JavaWeb的两种开发模式
    [转]javaweb学习总结(二十)——JavaBean总结
    [转]javaweb学习总结(十九)——JSP标签
    [转]javaweb学习总结(十八)——JSP属性范围
    [转]JavaWeb学习总结(十七)——JSP中的九个内置对象
    [转]javaweb学习总结(十六)——JSP指令
    [转]javaweb学习总结(十五)——JSP基础语法
    TypeScript
    TypeScript
  • 原文地址:https://www.cnblogs.com/yxwkf/p/5177764.html
Copyright © 2011-2022 走看看