zoukankan      html  css  js  c++  java
  • hdu_2444The Accomodation of Students(二分图的判定和计算)

    hdu_2444The Accomodation of Students(二分图的判定和计算)

    标签:二分图匹配


    题目链接

    题意:

    问学生是否能分成两部分,每一部分的人都不相认识,如果能分成的话,两两认识的人可以去开房哈。求最大的开房数。
    

    题解:

    二分染色,黑白染色来看这个图可以被染成一个二分图,如果可以的话求出二分图匹配的个数即可
    

    注意事项:

    dfs来染色,在求解的时候注意点的编号是从0还是从1开始的
    

    代码:

    //二分图最好用链表存图
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 1010;
    int vis[N];
    int v[N];
    int head[N];
    struct Edge{
        int to;
        int next;
    }edge[N*N];
    int Ecnt;
    int rm[N];
    int id[N];
    void init()
    {
        Ecnt = 0;
        memset(vis,0,sizeof(vis));
        memset(id,-1,sizeof(id));
        memset(rm,-1,sizeof(rm));
        memset(v,0,sizeof(v));
        memset(head,-1,sizeof(head));
    }
    void add(int from, int to){
        edge[Ecnt].to = to;
        edge[Ecnt].next = head[from];
        head[from] = Ecnt++;
        edge[Ecnt].to = from;
        edge[Ecnt].next = head[to];
        head[to] = Ecnt++;
    }
    bool dfs(int s,int type){
        id[s] = type;
        for(int i = head[s]; i != -1; i = edge[i].next)
        {
            int t = edge[i].to;
            if(id[t]!=-1&&id[t]!=!type) return 0;
            if(v[t]==0){
                v[t] = 1;
               if( dfs(t,!type)==0) return 0;
            }
        }
        return 1;
    }
    int list(int s){
        for(int i = head[s]; i!= -1; i= edge[i].next){
            int t = edge[i].to;
            if(vis[t]) continue;
            vis[t] = 1;
            if(rm[t]==-1||list(rm[t])){
                rm[t] = s;
                return 1;
            }
        }
        return 0;
    }
    int Max_match(int n)
    {
        int ans = 0;
        for(int i = 0; i < n; i++){
            memset(vis,0,sizeof(vis));
            vis[i] = 1;
            if(list(i)) ans++;
        }
        return ans;
    }
    int main()
    {
        int n,m;
        int x, y;
        while(~scanf("%d%d",&n,&m))
        {
            init();
            for(int i = 0; i < m; i++){
                scanf("%d%d",&x,&y);
                x--;y--;//加边的时候要注意点的编号是从什么开始的
                add(x,y);
            }
            bool fl = 1;
            for(int i = 0; i < n; i++){
                if(v[i])continue;
                if(dfs(i,0)==0){fl = 0;continue;}
            }
            if(fl == 0) puts("No");
            else {
                   // puts("haha");
                int ans = Max_match(n);
                printf("%d
    ",ans/2);
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    VS2010插件及快捷键设置
    在Windows程序中启用console输出-2016.01.04
    使用VAssistX给文件和函数添加注释-2015.12.31
    windows在远程桌面连接中使用命令行参数
    windows网络编程-2015.12.29
    grep使用
    linux程序调试常用命令
    vim使用笔记
    infusion度量金字塔数据解释
    MVc Forms Membership rolemanage 角色权限验证管理
  • 原文地址:https://www.cnblogs.com/shanyr/p/5708014.html
Copyright © 2011-2022 走看看