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\n",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

你可能感兴趣的:(poj)