码迷,mamicode.com
首页 > 其他好文 > 详细

hunnu OJ 11564 Easy Delete(二维坐标的离散化处理+最大匹配)

时间:2015-08-10 16:14:10      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:

题意:?给出两类点坐标
–一类可删除
–一类不可删除
?选出最少的行或列,删除所有要删除的点。

思路
?首先看到坐标范围很大,第一点要做的就是离散化。
?接着,将行看成二分图的X集合,将列看成二分图的Y集合,于是,我们要删除的点,就是X连接Y的一条边。
?最后,我们要求的就是最少的点覆盖所有的边。在二分图中,最大匹配==最小点覆盖。
需要注意的地方
?判断每一个要删除的点,如果X方向和Y方向都有不能删除的点,就是Sorry。
?
?如果只有一个方向有,则必须使用另外一个方向删除该行/列的所有点。
?
剩下的点使用二分图最大匹配

AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

#define clr(a,b) memset(a,b,sizeof(a))
const int maxn = 1005;

struct H
{
    int x,y,id,z;
}no[maxn];

bool cmp1(H a,H b){return a.x<b.x;}
bool cmp2(H a,H b){return a.y<b.y;}

int nx[maxn],ny[maxn],nz[maxn];
int mp[maxn][maxn],mm[maxn][maxn];

int vx[maxn],vy[maxn];
int cx[maxn],cy[maxn];
int vis[maxn],sign[maxn];
int cnx,cny;

int dfs(int x)
{
    for(int i=0;i<cny;i++)
    {
        if(!vis[i]&&mp[x][i])
        {
            vis[i]=1;
            if(sign[i] == -1||dfs(sign[i]))
            {
                sign[i]=x;
                return 1;
            }
        }
    }
    return 0;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("E.txt","r",stdin);
    freopen("out.cpp","w",stdout);
#endif // ONLINE_JUDGE
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++){
            scanf("%d%d%d",&no[i].z,&no[i].x,&no[i].y);
            no[i].id=i;
        }
        sort(no,no+n,cmp1);
        cnx=-1;
        nx[no[0].id]=++cnx;
        for(int i=1;i<n;i++) {
            if(no[i].x==no[i-1].x) 
                nx[no[i].id]=cnx;
            else nx[no[i].id]=++cnx;
        }
        sort(no,no+n,cmp2);
        cny=-1;
        ny[no[0].id]=++cny;
        for(int i=1;i<n;i++) {
            if(no[i].y==no[i-1].y) 
                ny[no[i].id]=cny;
            else ny[no[i].id]=++cny;
        }
        cnx++;
        cny++;
        for(int i=0;i<n;i++) 
            nz[no[i].id]=no[i].z;

        clr(mp,0);clr(vx,0);clr(vy,0);
        for(int i=0;i<n;i++) {
            if(nz[i]) mp[nx[i]][ny[i]]=1;
            else{
                vx[nx[i]]=1;vy[ny[i]]=1;
            }
        }

        int flag=0;
        for(int i=0;i<cnx;i++){
            if(vx[i]){
                for(int j=0;j<cny;j++){
                    if(vy[j]) {if(mp[i][j]){flag=1;break;}}
                }
            }
            if(flag) break;
        }
        if(flag) {printf("Sorry\n");continue;}
        int ans=0;
        clr(cx,0);clr(cy,0);
        for(int i=0;i<cnx;i++){
            if(vx[i]){
                for(int j=0;j<cny;j++) if(mp[i][j]) {cy[j]=1;}
            }
        }

        for(int i=0;i<cny;i++){
            if(vy[i]){
                for(int j=0;j<cnx;j++) if(mp[j][i]) {cx[j]=1;}
            }
        }

        for(int i=0;i<cnx;i++){
            if(cx[i]) {ans++;for(int j=0;j<cny;j++) if(mp[i][j])mp[i][j]=0;}
        }
        for(int i=0;i<cny;i++){
            if(cy[i]) {
                ans++;for(int j=0;j<cnx;j++) if(mp[j][i])mp[j][i]=0;
            }
        }

        memset(sign,-1,sizeof(sign));
        for(int i=0;i<cnx;i++)
        {
            memset(vis,0,sizeof(vis));
            if(dfs(i))
                ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}




版权声明:本文为博主原创文章,未经博主允许不得转载。

hunnu OJ 11564 Easy Delete(二维坐标的离散化处理+最大匹配)

标签:

原文地址:http://blog.csdn.net/u012313382/article/details/47399309

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!