POJ 1548 (二分图+最小路径覆盖)

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

题目大意:给出一张地图上的垃圾,以及一堆机器人。每个机器人可以从左->右,上->下。走完就废。问最少派出多少个机器人才能捡完所有垃圾。

解题思路

本题原本是个LIS题。但是有二分图匹配解法。

类似POJ 3020的覆盖题,先不管机器人。把每个点都看作一个中心点。然后从这个点出发,向右、下方向连边,这样这个点就可以看作派出的机器人了。

由于方向固定,怎么连都不会连出反向边,所以是个天然有向图。

跑一遍Hungry,ans=垃圾数-match。


    #include "cstdio"
    #include "vector"
    #include "cstring"
    using namespace std;
    vector<int> G[30*30];
    int link[30*30];
    bool vis[30*30];
    struct point
    {
        int x,y;
    };
    bool dfs(int u)
    {
        for(int v=0;v<G[u].size();v++)
        {
            if(vis[G[u][v]]) continue;
            vis[G[u][v]]=true;
            if(link[G[u][v]]==-1||dfs(link[G[u][v]]))
            {
                link[G[u][v]]=u;
                return true;

            }
        }
        return false;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        point tt;
        vector<point> pos;
        int cnt=0,ans=0;
        while(scanf("%d%d",&tt.x,&tt.y)&&tt.x!=-1&&tt.y!=-1)
        {
            if(tt.x==0&&tt.y==0)
            {
                for(int i=0;i<cnt;i++)
                {
                    for(int j=0;j<cnt;j++)
                    {
                        if(i==j) continue;
                        if(pos[i].x<=pos[j].x&&pos[i].y<=pos[j].y) G[i].push_back(j);
                    }
                }
                memset(link,-1,sizeof(link));
                for(int i=0;i<cnt;i++)
                {
                    memset(vis,0,sizeof(vis));
                    if(dfs(i)) ans++;
                }
                printf("%d
",cnt-ans);
                cnt=ans=0;
                pos.clear();
                for(int i=0;i<30*30;i++) G[i].clear();
                continue;
            }
            pos.push_back(tt);
            cnt++;
        }
    }
13260799 neopenx 1548 Accepted 652K 32MS C++ 1361B 2014-08-06 23:02:14
原文地址:https://www.cnblogs.com/neopenx/p/4009789.html