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

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的话。估计要贪心一下了。

 

posted @   jlins  阅读(225)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示