uva 1345 Jamie's Contact Groups (最大流+二分)

uva 1345 Jamie’s Contact Groups

Description

Jamie is a very popular girl and has quite a lot of friends, so she always keeps a very long contact list in her cell phone. The contact list has become so long that it often takes a long time for her to browse through the whole list to find a friend’s number. As Jamie’s best friend and a programming genius, you suggest that she group the contact list and minimize the size of the largest group, so that it will be easier for her to search for a friend’s number among the groups. Jamie takes your advice and gives you her entire contact list containing her friends’ names, the number of groups she wishes to have and what groups every friend could belong to. Your task is to write a program that takes the list and organizes it into groups such that each friend appears in only one of those groups and the size of the largest group is minimized.

Input

There will be at most 20 test cases. Ease case starts with a line containing two integers N and M. where N is the length of the contact list and M is the number of groups. N lines then follow. Each line contains a friend’s name and the groups the friend could belong to. You can assume N is no more than 1000 and M is no more than 500. The names will contain alphabet letters only and will be no longer than 15 characters. No two friends have the same name. The group label is an integer between 0 and M - 1. After the last test case, there is a single line `0 0’ that terminates the input.

Output

For each test case, output a line containing a single integer, the size of the largest contact group.

Sample Input

3 2

John 0 1

Rose 1

Mary 1

5 4

ACM 1 2 3

ICPC 0 1

Asian 0 2 3

Regional 1 2

ShangHai 0 2

0 0

Sample Output

2

2

题目大意:给出一些人,和他们可能加入的组号。问每个组,最小的最大人数是多少。

解题思路:看到最小的最大值就想到二分,问题是二分什么。这题二分的是最大流的容量。设置一个超级源点,连向所有的人,容量为1。设置一个超级汇点,使所有的组连向超级汇点,二分的就是这里的容量(0~n)。然后根据题目给出的人和组的关系连接人和组,容量为1。二分时,若当前状态求出的最大流等于人数,则下界等于mid,若不等于,则上界等于mid。二分出的容量,就是组中的最小的最大人数。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <sstream>
#include <iostream>
using namespace std;

const int N = 1010 + 510;
const int M = 1010 * 510 * 4;
const int PO = 1005;
const int INF = 0x3f3f3f3f;
typedef long long ll;
int n, m, s, t, rec[PO][PO], cnt[PO];
int ec, head[N], first[N], que[N], lev[N];
int Next[M], to[M], v[M];  

void init() {
    ec = 0;
    memset(first, -1, sizeof(first));
}  

void addEdge(int a,int b,int c) {
    to[ec] = b;
    v[ec] = c;
    Next[ec] = first[a];
    first[a] = ec++;  

    to[ec] = a;
    v[ec] = 0;
    Next[ec] = first[b];
    first[b] = ec++;
}  

int BFS() {
    int kid, now, f = 0, r = 1, i;
    memset(lev, 0, sizeof(lev));
    que[0] = s, lev[s] = 1;
    while (f < r) {
        now = que[f++];
        for (i = first[now]; i != -1; i = Next[i]) {
            kid = to[i];
            if (!lev[kid] && v[i]) {
                lev[kid] = lev[now] + 1;
                if (kid == t) return 1;
                que[r++] = kid;
            }
        }
    }
    return 0;
}  

int DFS(int now, int sum) {
    int kid, flow, rt = 0;
    if (now == t) return sum;
    for (int i = head[now]; i != -1 && rt < sum; i = Next[i]) {
        head[now] = i;
        kid = to[i];
        if (lev[kid] == lev[now] + 1 && v[i]) {
            flow = DFS(kid, min(sum - rt, v[i]));
            if (flow) {
                v[i] -= flow;
                v[i^1] += flow;
                rt += flow;
            } else lev[kid] = -1;
        }
    }
    return rt;
}  

int dinic() {
    int ans = 0;
    while (BFS()) {
        for (int i = 0; i <= t; i++) {
            head[i] = first[i];
        }
        ans += DFS(s, INF);
        if (ans >= n) return ans;
    }
    return ans;
}     

void input() {
    init();
    s = 0, t = (n + m) + 2;
    memset(cnt, 0 ,sizeof(cnt));
    char ch[100];
    int num;
    string ss;
    for (int i = 0; i < n; i++) {
        getline(cin, ss);
        stringstream stream(ss);
        stream >> ch;
        while (stream >> num) {
            addEdge(i + 1, num + 1 + n, 1);
        }
    }
    for (int i = 1; i <= n; i++) {
        addEdge(s, i, 1);
    }
    for (int i = 1; i <= m; i++) {
        addEdge(i + n, t, 1);
    }
}

int build(int x) {
    for (int i = 0; i < ec; i += 2) {
        if (to[i] == t) v[i] = x;
        else v[i] = 1;
        v[i^1] = 0;
    }
    int temp = dinic();
    if (temp == n) return 1;
    else return 0;
}

int main() {
    while (scanf("%d %d\n", &n, &m) == 2, (n || m)) {
        input();
        int L = 0, R = n + 2;
        while (L < R) {
            int mid = (L + R) / 2;
            if (build(mid)) R = mid;
            else L = mid + 1;
        }
        printf("%d\n", L);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许也可以转载,不过要注明出处哦。

uva 1345 Jamie's Contact Groups (最大流+二分)

时间: 2024-10-10 12:51:08

uva 1345 Jamie's Contact Groups (最大流+二分)的相关文章

UVA 1345 - Jamie&#39;s Contact Groups(二分+最大流)

UVA 1345 - Jamie's Contact Groups 题目链接 题意:给定一些人,每个人有一个分组,现在要每个人选一个分组,使得所有分组中最大的人数最小,问这个最小值是多少 思路:二分答案,然后利用最大流去判定,源点往每个人建一条边容量为1,每个人往各自的分组建一条边,容量为1,分组向汇点建一条边,容量为二分出来的值,这样跑一下最大流如果最大流等于n,就是能满足 代码: #include <cstdio> #include <cstring> #include <

UVA 1345 Jamie&#39;s Contact Groups

题意: 一些人,和他们可能加入的组号.问每个组,最小的最大人数是多少 分析: 二分的是最大流的容量.设置一个超级源点,连向所有的人,容量为1.设置一个超级汇点,使所有的组连向超级汇点,二分的就是这里的容量(0-n).然后根据题目给出的人和组的关系连接人和组,容量为1.二分时,若当前状态求出的最大流等于人数,则下界等于mid,若不等于,则上界等于mid.二分出的容量,就是组中的最小的最大人数. 输入: 3 2 John 0 1 Rose 1 Mary 1 5 4 ACM 1 2 3 ICPC 0

UValive3268 Jamie&#39;s Contact Groups(二分+最大流)

题目地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1269 Jamie is a very popular girl and has quite a lot of friends, so she always keeps a very long contact list in her cell phone. The c

UVALive-3268 Jamie&#39;s Contact Groups (最大流,网络流建模)

题目大意:你的手机通讯录里有n个联系人,m个分组,其中,有的联系人在多个分组里.你的任务是在一些分组里删除一些联系人,使得每个联系人只在一个分组里并且使人数最多的那个分组人数最少.找出人数最多的那个分组中的人数. 题目分析:要求的是最小的最大值,二分枚举这个最小的最大人数x.增加源点s和汇点t,从s向每一个联系人连一条弧,容量为1,表示一个联系人只能在一个分组中:然后对于每个联系人向他所在的分组连一条弧,容量为1,表示在这个分组里最多保存一次该联系人:然后从每个分组向汇点连一条弧,容量为x,表示

POJ 2289 Jamie&#39;s Contact Groups (二分+最大流)

题目大意: 有n个人,可以分成m个组,现在给出你每个人可以去的组的编号,求分成的m组中人数最多的组最少可以有多少人. 算法讨论: 首先喷一下这题的输入,太恶心了. 然后说算法:最多的最少,二分的字眼.二分什么,因为我们说的是组的人,所以要对组的流出量进行二分.其余的都连流量为1的边,然后对“小组”点的流出量二分连边,最后跑最大流判断 是否等于N即可.还是蛮简单的. Codes: 1 #include <cstdio> 2 #include <cstring> 3 #include

poj 2289 —— Jamie&#39;s Contact Groups 二分+最大流

原题:http://poj.org/problem?id=2289 #include<cstdio> #include<cstring> #include<string> #include<queue> #include<vector> #include<map> #include<algorithm> #define inf 1e9 using namespace std; const int maxn = 2000;

POJ2289 Jamie&#39;s Contact Groups —— 二分图多重匹配/最大流 + 二分

题目链接:https://vjudge.net/problem/POJ-2289 Jamie's Contact Groups Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 8147   Accepted: 2736 Description Jamie is a very popular girl and has quite a lot of friends, so she always keeps a very lon

解题报告 之 POJ2289 Jamie&#39;s Contact Groups

解题报告 之 POJ2289 Jamie's Contact Groups Description Jamie is a very popular girl and has quite a lot of friends, so she always keeps a very long contact list in her cell phone. The contact list has become so long that it often takes a long time for her

POJ 2289 Jamie&#39;s Contact Groups

二分答案+网络最大流 #include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; int N,M; const int maxn = 2000 + 10; const int INF = 0x7FFFFFFF; struct Edge { int