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

来源:互联网 发布:c语言二维数组例子 编辑:程序博客网 时间:2024/06/06 03:20
题意:•给出两类点坐标
–一类可删除
–一类不可删除
•选出最少的行或列,删除所有要删除的点。

思路
•首先看到坐标范围很大,第一点要做的就是离散化。
•接着,将行看成二分图的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;}


0 0