zoukankan      html  css  js  c++  java
  • HDU 2063 单向二分匹配裸题(超恶心呢)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2063

    很长时间没做二分图的题,今天挑个简单了温习下。没想到。。。。

    二分图是没有有向图和有向图的概念吧。那这道题用双向图建图可能会被坑死吧。我用双向图交了n遍都不能过。

    或许是后台数据男孩和女孩编号可能会大于a,b吧?那么你用mp的话点数就要开大一点了,不止500了。

    WA代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int maxn = 1000+5;
    int e[maxn][maxn];
    int match[maxn];
    int book[maxn];
    int k;
    int n;
    int a,b;
    
    int dfs(int u)
    {
        for(int i=1; i<=n; i++)
        {
            if(book[i]==0 && e[u][i]==1)
            {
                book[i]=1; //标记点i已访问过
                if(match[i]==0||dfs(match[i]))
                {
                    //更新配对关系
                    match[i]=u;
                    match[u]=i;
                    return 1;
                }
            }
        }
        return 0;
    }
    int main()
    {
    //   freopen("in.txt","r",stdin);
        int sum;
    
        while(scanf("%d",&k)&&k!=0)
        {
            scanf("%d%d",&a,&b);
            sum = 0;
            n = a+b;
            memset(e,0,sizeof(e));
            memset(book,0,sizeof(book));
            memset(match,0,sizeof(match));
            sum=0;
    
            for(int i = 1; i <= k; i++)
            {
                int t1,t2;
                scanf("%d%d",&t1,&t2);
                t2 += a;
                e[t1][t2] = 1;
                e[t2][t1] = 1;
            }
    
    
            for(int i=1; i<=n; i++)
            {
                memset(book,0,sizeof(book));//清空上次搜索时的标记
    
                if(dfs(i))
                    sum++;     //寻找增广路,如果找到,配对数加1.
            }
            printf("%d
    ",sum);
        }
        return 0;
    }

    如果出现编号大于a的情况,加a不够吧,那我+500?还是WA。。

    他么的,我加1000吧,然后过了。。。。诶,没意思。

    双向的话,把编号当做下标的话,遍历的时候,是要比最大的下标为最后一个,所以dfs的时候也要到maxn,因为match可能到达那里。。。

    你双向建图的话
    两边编号要分开
     男孩的编号就要+上最大那个女孩的编号

    AC:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int maxn = 2000+5;
    int e[maxn+5][maxn+5];
    int match[maxn+5];
    int book[maxn+5];
    int k;
    int n;
    int a,b;
    
    int dfs(int u)
    {
        for(int i=1; i<maxn; i++)
        {
            if(book[i]==0 && e[u][i]==1)
            {
                book[i]=1; //标记点i已访问过
                if(match[i]==0||dfs(match[i]))
                {
                    //更新配对关系
                    match[i]=u;
                    match[u]=i;
                    return 1;
                }
            }
        }
        return 0;
    }
    int main()
    {
    //   freopen("in.txt","r",stdin);
        int sum;
    
        while(scanf("%d",&k)&&k!=0)
        {
            scanf("%d%d",&a,&b);
            sum = 0;
            n = a+b;
            memset(e,0,sizeof(e));
            memset(book,0,sizeof(book));
            memset(match,0,sizeof(match));
            sum=0;
    
            for(int i = 1; i <= k; i++)
            {
                int t1,t2;
                scanf("%d%d",&t1,&t2);
                t2 += 1000;
                e[t1][t2] = 1;
                e[t2][t1] = 1;
            }
    
    
            for(int i=1; i<=n; i++)
            {
                memset(book,0,sizeof(book));//清空上次搜索时的标记
    
                if(dfs(i))
                    sum++;     //寻找增广路,如果找到,配对数加1.
            }
            printf("%d
    ",sum);
        }
        return 0;
    }

    傻逼吧,还是单向建图轻松一点,只要一边女孩连完了,就结束了...

    AC:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int maxn = 1000+5;
    int e[maxn][maxn];
    int match[maxn];
    int book[maxn];
    int k;
    int n;
    int a,b;
    
    int dfs(int u)
    {  

      //每个女生连通男孩的边最多为b,枚举最多可能b的边
    for(int i=1; i<=b; i++) { if(book[i]==0 && e[u][i]==1) { book[i]=1; //标记点i已访问过 if(match[i]==0||dfs(match[i])) { //更新配对关系 match[i]=u; return 1; } } } return 0; } int main() { // freopen("in.txt","r",stdin); int sum; while(scanf("%d",&k)&&k!=0) { scanf("%d%d",&a,&b); sum = 0; n = a+b; memset(e,0,sizeof(e)); memset(book,0,sizeof(book)); memset(match,0,sizeof(match)); sum=0; for(int i = 1; i <= k; i++) { int t1,t2; scanf("%d%d",&t1,&t2); e[t1][t2] = 1; }      //每个女生必须找个男生,所以每个女生搜一遍就可以了 for(int i=1; i<=a; i++) { memset(book,0,sizeof(book));//清空上次搜索时的标记 if(dfs(i)) sum++; //寻找增广路,如果找到,配对数加1. } printf("%d ",sum); } return 0; }

    这题跟啊哈算法上面的例子不同就在编号上,编号和人数是分开的。=-=

    但是别人用的这个Vector 加了女生的数量为什么就A了呢,求解啊!!!

    #include <cmath>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define met(a,b) memset(a,b,sizeof(a))
    #define inf 0x3f3f3f3f
    const int maxn = 1000+10;
    vector<int> p[maxn];
    int match[maxn];
    bool visited[maxn];
    
    void add(int u,int v)
    {
        p[u].push_back(v);
        p[v].push_back(u);
    }
    
    bool dfs(int u)
    {
        visited[u]=true;
        for(int i=0;i<p[u].size();i++)
        {
            int v=p[u][i];
            if(!visited[v])
            {
                visited[v]=true;
                if(match[v]==-1||dfs(match[v]))
                {
                    match[v]=u;
                    match[u]=v;
                    return true;
                }
            }
        }
        return false;
    }
    
    int main()
    {
        int  k,n,m;
        while(scanf("%d%d%d",&k,&n,&m)!=EOF&&k!=0)
        {
            for(int i=1;i<=max(n,m);i++)
                p[i].clear();
            for(int i=0;i<k;i++)
            {
                int a,b;
                scanf("%d%d",&a,&b);
                b+=n+1;
                add(a,b);
            }
            int ans=0;
            met(match,-1);
            for(int i=1;i<=n;i++)
            {
                met(visited,false);
                if(dfs(i))
                    ans++;
            }
            printf("%d
    ",ans);
        }
    }

    所以单向建图吧!

  • 相关阅读:
    转: React系统的入门系统
    转: Android官方培训课程中文版(v0.9.5)
    释放Linux系统缓存
    Hyperledger Fabric1.0环境搭建
    JS中的call、apply、bind
    资产和负债
    JS以指定格式获取当前日期
    apache2.4配置ssl
    Apache2.4整合tomcat8
    使用JDK将tomcat变成https访问
  • 原文地址:https://www.cnblogs.com/zhangmingzhao/p/7231074.html
Copyright © 2011-2022 走看看