zoukankan      html  css  js  c++  java
  • 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+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+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+m-hopcroft_MaxMatch_Vector());
        }
        return 0;
    }
    
    


    如果要达到0MS的话。估计要贪心一下了。
  • 相关阅读:
    Tarjan算法
    10JS数组
    9JS循环
    8.JS流程控制
    7.JS运算符
    6.JS方法
    5.JS变量的各种问题
    java封装遇到的问题
    js报Uncaught SyntaxError: Unexpected token <错误 解决方法:
    使用layui出现Uncaught ReferenceError: layui is not defined问题解决:
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3220335.html
Copyright © 2011-2022 走看看