HDU 多校联合练习赛2 Warm up 2 二分图匹配

73 篇文章 21 订阅
56 篇文章 0 订阅

Warm up 2

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 656    Accepted Submission(s): 329


Problem Description
  Some 1×2 dominoes are placed on a plane. Each dominoe is placed either horizontally or vertically. It's guaranteed the dominoes in the same direction are not overlapped, but horizontal and vertical dominoes may overlap with each other. You task is to remove some dominoes, so that the remaining dominoes do not overlap with each other. Now, tell me the maximum number of dominoes left on the board.
 

Input
  There are multiple input cases.
  The first line of each case are 2 integers: n(1 <= n <= 1000), m(1 <= m <= 1000), indicating the number of horizontal and vertical dominoes.
Then n lines follow, each line contains 2 integers x (0 <= x <= 100) and y (0 <= y <= 100), indicating the position of a horizontal dominoe. The dominoe occupies the grids of (x, y) and (x + 1, y).
  Then m lines follow, each line contains 2 integers x (0 <= x <= 100) and y (0 <= y <= 100), indicating the position of a horizontal dominoe. The dominoe occupies the grids of (x, y) and (x, y + 1).
  Input ends with n = 0 and m = 0.
 

Output
  For each test case, output the maximum number of remaining dominoes in a line.
 

Sample Input
  
  
2 3 0 0 0 3 0 1 1 1 1 3 4 5 0 1 0 2 3 1 2 2 0 0 1 0 2 0 4 1 3 2 0 0
 

Sample Output
  
  
4 6
 

Source
 

Recommend
zhuyuanchen520
 

题解:
原来是我建图不会建。。。果然是基础功不扎实啊。。

原来就是个普通的最大独立集。  最大独立集的定义就是所选取的点集合中,任意两条边都不相连。 又因为题目中说横着的不会跟横着的相连,竖着的不会跟竖着的相连,所以。这是个相当标准的二分图。就是求X集合跟Y集合的最大独立集。    

建造图时,X取的是那0到n-1个骨牌   Y取的是后面的0到m-1个骨牌。。。无语撒。。原来当初我2分图完全弄错了。。

这题解法好像很多。。什么搜索,贪心。。不说了。。。牢记不会建图的教训。。

我提供下我写的3份模板代码吧。。。。

第一份 33MS
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstring>
const int maxn=1111;
int g[maxn][maxn];
int cx[maxn],cy[maxn],vst[maxn];
int nx,ny;
int findpath(int u){
    for(int v=0;v<ny;v++){
        if(!vst[v]&&g[u][v]){
            vst[v]=1;
            if(cy[v]==-1||findpath(cy[v])){
                cy[v]=u,cx[u]=v;
                return 1;
            }
        }
    }
    return 0;
}
int MaxMatch(){
    int ret=0;
    memset(cx,-1,sizeof(cx));
    memset(cy,-1,sizeof(cy));
    for(int i=0;i<nx;i++)
        if(cx[i]==-1){
            memset(vst,0,sizeof(vst));
            if(findpath(i))
                ret++;
        }
    return ret;
}
struct node{
    int x,y;
}mx[maxn],my[maxn];
int main(){
    //freopen("1009.in","r",stdin);
    int n,m;
    while(scanf("%d %d",&n,&m)&&n+m){
        for(int i=0,a,b;i<n;i++){
            scanf("%d %d",&a,&b);
            mx[i].x=a,mx[i].y=b;
        }
        for(int i=0,a,b;i<m;i++){
            scanf("%d %d",&a,&b);
            my[i].x=a,my[i].y=b;
        }
        memset(g,0,sizeof(g));
        for(int i=0,x1,y1;i<n;i++){
            x1=mx[i].x,y1=mx[i].y;
            for(int j=0,x2,y2;j<m;j++){
                x2=my[j].x,y2=my[j].y;
                if(x1==x2&&y1==y2
                 ||x1==x2&&y1==y2+1
                 ||x1+1==x2&&y1==y2
                 ||x1+1==x2&&y1==y2+1)
                 g[i][j]=1;
            }
        }
        nx=n,ny=m;
        printf("%d\n",n+m-MaxMatch());
    }
    return 0;
}

第2份:15MS
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#define clr(x,k) memset((x),(k),sizeof(x))
#define foreach(it,c) for(vi::iterator it = (c).begin();it != (c).end();++it)
using namespace std;
typedef vector<int> vi;

const int maxn=1000;
vector<int> gx[maxn];
int cx[maxn],cy[maxn],vst[maxn];
int nx,ny;
int findpath_Vector(int u){
    foreach(it,gx[u]){
        if(!vst[*it]){
            vst[*it]=1;
            if(cy[*it]==-1||findpath_Vector(cy[*it])){
                    cx[u]=*it;
                    cy[*it]=u;
                    return 1;
            }
        }
    }
    return 0;
}
int maxMatch_Vector(){
    int ret=0;
    clr(cx,-1),clr(cy,-1);
    for(int i=0;i<nx;i++)
        if(cx[i]==-1){
                clr(vst,0);
                if(findpath_Vector(i))
                    ret++;
        }
    return ret;
}
struct node{
    int x,y;
}mx[maxn],my[maxn];
int main(){
   // freopen("1009.in","r",stdin);
    int n,m;
    while(scanf("%d %d",&n,&m)&&n+m){
        for(int i=0,a,b;i<n;i++){
            scanf("%d %d",&a,&b);
            mx[i].x=a,mx[i].y=b;
        }
        for(int i=0,a,b;i<m;i++){
            scanf("%d %d",&a,&b);
            my[i].x=a,my[i].y=b;
        }
        for(int i=0;i<n;i++)
            gx[i].clear();
        for(int i=0,x1,y1;i<n;i++){
            x1=mx[i].x,y1=mx[i].y;
            for(int j=0,x2,y2;j<m;j++){
                x2=my[j].x,y2=my[j].y;
                if(x1==x2&&y1==y2
                 ||x1==x2&&y1==y2+1
                 ||x1+1==x2&&y1==y2
                 ||x1+1==x2&&y1==y2+1)
                 gx[i].push_back(j);
            }
        }

        nx=n,ny=m;
        printf("%d\n",n+m-maxMatch_Vector());
    }
    return 0;
}

第3份 15MS。  hy这个算法应该会快点的。可能是因为题目有点特殊,没有体现。
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <iostream>
#define clr(x,k) memset((x),(k),sizeof(x))
#define foreach(it,c) for(vi::iterator it = (c).begin();it != (c).end();++it)
using namespace std;
typedef vector<int> vi;

const int INF=1<<28;
const int maxn=1000;
int cx[maxn],cy[maxn];
vi gx[maxn];
int dx[maxn],dy[maxn];
int dis,nx;
int vst[maxn];
bool searchpath(){
    queue<int> Q;
    dis=INF;
    clr(dx,-1),clr(dy,-1);
    for(int i=0;i<nx;i++){
        if(cx[i]==-1)
            Q.push(i),dx[i]=0;
    }
    while(!Q.empty()){
        int u=Q.front();Q.pop();
        if(dx[u]>dis) break;
        foreach(it,gx[u])
            if(dy[*it]==-1){
                dy[*it]=dx[u]+1;
                if(cy[*it]==-1) dis=dy[*it];
                else{
                    dx[cy[*it]]=dy[*it]+1;
                    Q.push(cy[*it]);
                }
            }
    }
    return dis!=INF;
}
int hop_Findpath_Vector(int u){
    foreach(it,gx[u]){
        if(!vst[*it]&&dy[*it]==dx[u]+1){//说明这是一条增广路径。但还需判断
            vst[*it]=1;
            if(cy[*it]!=-1&&dy[*it]==dis) //出现这种情况。说明不是增广路, 因为最后一条增路是 cy[v]==-1&&dy[v]==dis
                continue;
            if(cy[*it]==-1||hop_Findpath_Vector(cy[*it])){
                cy[*it]=u,cx[u]=*it;
                return 1;
            }
        }
    }
    return 0;
}
int hopcroft_MaxMatch_Vector(){
    int res=0;
    clr(cx,-1),clr(cy,-1);
    while(searchpath()){
        clr(vst,0);
        for(int i=0;i<nx;i++){
            if(cx[i]==-1){
                res+=hop_Findpath_Vector(i);
            }
        }
    }
    return res;
}
struct node{
    int x,y;
}mx[maxn],my[maxn];
int main(){
    //freopen("1009.in","r",stdin);
    int n,m;
    while(scanf("%d %d",&n,&m)&&n+m){
        for(int i=0,a,b;i<n;i++){
            scanf("%d %d",&a,&b);
            mx[i].x=a,mx[i].y=b;
        }
        for(int i=0,a,b;i<m;i++){
            scanf("%d %d",&a,&b);
            my[i].x=a,my[i].y=b;
        }
        for(int i=0;i<n;i++)
            gx[i].clear();
        for(int i=0,x1,y1;i<n;i++){
            x1=mx[i].x,y1=mx[i].y;
            for(int j=0,x2,y2;j<m;j++){
                x2=my[j].x,y2=my[j].y;
                if(x1==x2&&y1==y2
                 ||x1==x2&&y1==y2+1
                 ||x1+1==x2&&y1==y2
                 ||x1+1==x2&&y1==y2+1)
                 gx[i].push_back(j);
            }
        }

        nx=n;
        printf("%d\n",n+m-hopcroft_MaxMatch_Vector());
    }
    return 0;
}



如果要达到0MS的话。估计要贪心一下了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值