zoukankan      html  css  js  c++  java
  • POJ 3020 (二分图+最小路径覆盖)

    题目链接:http://poj.org/problem?id=3020

    题目大意:读入一张地图。其中地图中圈圈代表可以布置卫星的空地。*号代表要覆盖的建筑物。一个卫星的覆盖范围是其周围上下左右四个点。问最少需要几个卫星才能覆盖所有建筑物。

    解题思路

    有点类似POJ 1328的覆盖题,不过那题比较简单可以贪心。这题你可以YY试试。

    覆盖问题其实可以用图论解决。这题就属于最小路径覆盖,手动由一个点出发连一些路径,这样Hungry就能求出最少需要多少这样的中心点,就可以达成目标了。

    本题最大的疑问是到底是建有向图,还是无向图。由于Hungry只适用于有向图,所以好像应该建有向图。但是扫描这个图的时候,Hash图上点不算简单,需要对n*m标个号,然后Hash。

    建无向图其实也不是很简单,需要拆点,模拟出所谓的“有向图”来Hungry,本点放在X集,影子点放在Y集,如果有边(u,v),则u连v'(本点连影子点),对邻接矩阵每个城市相邻四个点扫一下加下边,这样自动模拟出"有向图"。

    跑一遍Hungry,ans=建筑物数-match/2。(无向图match是两倍)

    #include "iostream"
    #include "cstdio"
    #include "cstring"
    #include "string"
    #include "fstream"
    using namespace std;
    int G[401][401],link[401];
    int map[410][410];
    bool vis[801];
    int Case,n,m,pos;
    void AddEdge(int x,int y)
    {
        G[x][y]=1; //本点连影子点
    }
    bool dfs(int u)
    {
        for(int v=1;v<=pos;v++)
        {
            if(G[u][v]&&!vis[v])
            {
                vis[v]=true;
                if(!link[v]||dfs(link[v]))
                {
                    link[v]=u;
                    return true;
                }
            }
        }
        return false;
    }
    int main()
    {
        #define fin cin
        ifstream fin("in.txt");
        string line;
        cin>>Case;
        while(Case--)
        {
            pos=0;
            int res=0;
            cin>>n>>m;
            getline(cin,line);
            for(int i=1;i<=n;i++) //吸收残留
            {
                getline(cin,line);
                for(int j=0;j<line.size();j++)
                    if(line[j]=='*') map[i][j+1]=++pos;
            }
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    if(map[i][j]&&map[i-1][j]) AddEdge(map[i][j],map[i-1][j]);
                    if(map[i][j]&&map[i+1][j]) AddEdge(map[i][j],map[i+1][j]);
                    if(map[i][j]&&map[i][j-1]) AddEdge(map[i][j],map[i][j-1]);
                    if(map[i][j]&&map[i][j+1]) AddEdge(map[i][j],map[i][j+1]);
                }
            }
            for(int i=1;i<=pos;i++)
            {
                memset(vis,0,sizeof(vis));
                if(dfs(i)) res++;
            }
            res=pos-res/2;
            cout<<res<<endl;
            memset(map,0,sizeof(map));
            memset(G,0,sizeof(G));
            memset(link,0,sizeof(link));
        }
    }
  • 相关阅读:
    android 中使用AsyncTask实现简单的异步编程
    android TextView 垂直自动滚动
    (转)c3p0配置大全
    Android中在底端显示选项卡
    android 中ImageView的scaletype属性
    android 权限大全
    Palm应用开发之六 常用命令及debug
    android spinner 实现Text 和 value
    [转载]【职场宝典】面试官如何看待学历?
    起跑
  • 原文地址:https://www.cnblogs.com/neopenx/p/4009767.html
Copyright © 2011-2022 走看看