zoukankan      html  css  js  c++  java
  • POJ 2289 Jamie's Contact Groups(多重匹配+二分)

    题意:
    Jamie有很多联系人,但是很不方便管理,他想把这些联系人分成组,已知这些联系人可以被分到哪个组中去,而且要求每个组的联系人上限最小,即有一整数k,使每个组的联系人数都不大于k,问这个k最小是多少?
    题目分析:
    多重匹配,二分枚举所有极限值。
    多重匹配如何匹配?
    假如我们有两个集合X, Y 但是呢 Y可以匹配多个X, 这个时候我们需要给这个匹配设置一个极限值。比如Y可以匹配三个X。 假如匹配的值不到三个X我们就将他们匹配,
    直到到达极限值为止。在这里Y要保存所有的与之匹配的X,若是匹配值满了,进行Find()匹配就行了。
     
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<queue>
    #include<cmath>
    using namespace std;
    #define INF 0x3fffffff
    #define maxn 1505
    int n, m;
    bool G[maxn][maxn], vis[maxn];
    vector<vector<int> >Group;
    
    bool Find(int u,int limt)
    {
        for(int i=0; i<m; i++)
        {
            if(G[u][i] && !vis[i])
            {
                vis[i] = true;
                if( Group[i].size() < limt )
                {
                    Group[i].push_back(u);
                    return true;
                }
                for(int j=0; j < Group[i].size(); j++)
                {
                    if( Find(Group[i][j], limt) )
                    {
                        Group[i].erase(Group[i].begin()+j);
                        Group[i].push_back(u);
                        return true;
                    }
                }
            }
        }
        return false;
    }
    
    
    bool solve(int limt)
    {
        int num = 0;
        Group.clear();
        Group.resize(m+1);
        for(int i=0; i<n; i++)
        {
            memset(vis, false, sizeof(vis));
            if(Find(i, limt) )
                num ++;
        }
        return num == n;
    }
    
    int main()
    {
        int a;
        char ch;
        while(scanf("%d %d",&n, &m), n+m)
        {
            memset(G, false, sizeof(G));
            for(int i=0; i<n; i++)
            {
                scanf("%*s");
                while(1)
                {
                   // getchar();
                    scanf("%d%c",&a, &ch);
                    G[i][a] = true;
                    if(ch == '
    ')
                        break;
                }
            }
            int L = 0, R = n;
            while(L < R)
            {
                int mid = (L + R) / 2;
                if( solve(mid) )
                    R = mid;
                else
                    L = mid + 1;
            }
            printf("%d
    ", R);
        }
        return 0;
    }
  • 相关阅读:
    第十一章、集合
    第十章、正则表达式
    第九章、常用类
    第八章、面向对象高阶
    第七章、面向对象初识
    第六章、数组
    第五章、循环结构
    第四章、分支结构
    第三章、Java变量与数据类型
    Linux安装MySQL5.7(CentOS)
  • 原文地址:https://www.cnblogs.com/chenchengxun/p/4718609.html
Copyright © 2011-2022 走看看