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

    题意:Jamie有很多联系人,但是很不方便管理,他想把这些联系人分成组,已知这些联系人可以被分到哪个组中去,而且要求每个组的联系人上限最小,即有一整数k,使每个组的联系人数都不大于k,问这个k最小是多少?

    思路:这个题很像以前的那个星际战舰的那个题,一般就是二分答案,对每一个值进行建图,求最大流,查看这个最大流是否等于总人数,虽然比较繁琐,但是思路还是很清晰的,之后就是SAP模板了......(每次建图的时候一定要对信息进行初始化啊!!!WA了N次!)

    #include <iostream>
    #include
    <cstdio>
    #include
    <algorithm>
    #include
    <memory.h>
    #include
    <cmath>
    #include
    <bitset>
    #include
    <queue>
    #include
    <vector>
    using namespace std;

    const int BORDER = (1<<20)-1;
    const int MAXSIZE = 37;
    const int MAXN = 1508;
    const int INF = INT_MAX;

    #define CLR(x,y) memset(x,y,sizeof(x))
    #define ADD(x) x=((x+1)&BORDER)
    #define IN(x) scanf("%d",&x)
    #define OUT(x) printf("%d\n",x)
    #define MIN(m,v) (m)<(v)?(m):(v)
    #define MAX(m,v) (m)>(v)?(m):(v)
    #define ABS(x) ((x)>0?(x):-(x))

    int index,n,m,ans;
    int adj[MAXN][MAXN],in[MAXN];
    int nv,s,t;
    int net[MAXN];
    char str[20];

    struct Edge{
    int next,pair;
    int v,cap,flow;
    }edge[
    1500000];


    int init()
    {
    index
    = 0;
    CLR(net,
    -1);
    CLR(adj,
    0);
    CLR(
    in,0);
    ans
    = 0;
    return 0;
    }
    int input()
    {
    int i,j,tmp;
    char ch;
    getchar();
    for(i = 1;i <= n; i++)
    {
    ch
    = getchar();
    while((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
    ch
    = getchar();
    while(ch == ' ')
    ch
    = getchar();
    while(true)
    {
    j
    = 0;
    while(ch >= '0' && ch <= '9')
    {
    j
    = j * 10 + ch - '0';
    ch
    = getchar();
    }
    adj[i][j
    + 1] = 1;
    in[j + 1]++;
    if(ch == '\n') break;
    while(ch == ' ') ch = getchar();
    }
    }
    s
    = 0;
    nv
    = n + m + 2;
    t
    = nv - 1;
    return 1;
    }

    void add_edge(const int& u,const int& v,const int& val)
    {
    edge[index].next
    = net[u];
    net[u]
    = index;
    edge[index].v
    = v;
    edge[index].cap
    = val;
    edge[index].flow
    = 0;
    edge[index].pair
    = index+1;
    ++index;
    edge[index].next
    = net[v];
    net[v]
    = index;
    edge[index].v
    = u;
    edge[index].cap
    = 0;
    edge[index].flow
    = 0;
    edge[index].pair
    = index - 1;
    ++index;
    }
    int make_graph(const int& limit)
    {
    int i,j,tmp,k,u,v,val;
    CLR(net,
    -1);
    index
    = 0;
    for(i = 1; i <= n; ++i)
    add_edge(s,i,
    1);
    for(i = 1; i <= n; ++i)
    {
    for(j = 1; j <= m; ++j)
    if(adj[i][j])
    add_edge(i,j
    +n,1);
    }
    for(i = 1; i <= m; ++i)
    if(in[i] >= limit)
    add_edge(i
    +n,t,limit);
    else
    add_edge(i
    +n,t,in[i]);
    return 0;
    }
    int ISAP()
    {
    long numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN];
    long cur_flow,max_flow,u,tmp,neck,i;
    memset(dist,
    0,sizeof(dist));
    memset(numb,
    0,sizeof(numb));
    for(i = 1 ; i <= nv ; ++i)
    curedge[i]
    = net[i];
    numb[nv]
    = nv;
    max_flow
    = 0;
    u
    = s;
    while(dist[s] < nv)
    {
    /* first , check if has augmemt flow */
    if(u == t)
    {
    cur_flow
    = INF;
    for(i = s; i != t;i = edge[curedge[i]].v)
    {
    if(cur_flow > edge[curedge[i]].cap)
    {
    neck
    = i;
    cur_flow
    = edge[curedge[i]].cap;
    }
    }
    for(i = s; i != t; i = edge[curedge[i]].v)
    {
    tmp
    = curedge[i];
    edge[tmp].cap
    -= cur_flow;
    edge[tmp].flow
    += cur_flow;
    tmp
    = edge[tmp].pair;
    edge[tmp].cap
    += cur_flow;
    edge[tmp].flow
    -= cur_flow;
    }

    max_flow
    += cur_flow;
    u
    = s;
    }
    /* if .... else ... */
    for(i = curedge[u]; i != -1; i = edge[i].next)
    if(edge[i].cap > 0 && dist[u] == dist[edge[i].v]+1)
    break;
    if(i != -1)
    {
    curedge[u]
    = i;
    pre[edge[i].v]
    = u;
    u
    = edge[i].v;
    }
    else{
    if(0 == --numb[dist[u]]) break;
    curedge[u]
    = net[u];
    for(tmp = nv,i = net[u]; i != -1; i = edge[i].next)
    if(edge[i].cap > 0)
    tmp
    = tmp<dist[edge[i].v]?tmp:dist[edge[i].v];
    dist[u]
    = tmp + 1;
    ++numb[dist[u]];
    if(u != s) u = pre[u];
    }
    }
    return max_flow;
    }
    int work()
    {
    int low,high,mid,tmp;
    int pre;
    low
    = 0;
    high
    = -1;
    for(int i = 1; i <= m; ++i)
    high
    = MAX(high,in[i]);
    while(low <= high)
    {
    mid
    = (low + high)>>1;
    make_graph(mid);
    tmp
    = ISAP();
    if(tmp == n)
    {
    pre
    = mid;
    high
    = mid - 1;
    }
    else
    low
    = mid + 1;
    }
    printf(
    "%d\n",pre);
    return 0;
    }
    int main()
    {
    while(scanf("%d%d",&n,&m)!=EOF)
    {
    if(!n && !m)
    break;
    init();
    input();
    work();
    }
    return 0;
    }

  • 相关阅读:
    golang模拟动态高优先权优先调度算法
    【2019腾讯暑期实习生正式批笔试1,2】
    golang优先队列
    git常见操作
    小L的试卷
    Unable to connect to the Redgate Client Service. Sql Prompt 报错不能用解决
    未能加载文件或程序集“Microsoft.VisualStudio.Enterprise.AspNetHelper, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”或它的某一个依赖项。系统找不到指定的文件。
    LumiSoft 邮件操作删除(无法删除解决方法)
    .net MVC 项目中 上传或者处理进度获取方案
    C# mvc Request 请求过长报404错误的解决思路分析
  • 原文地址:https://www.cnblogs.com/lvpengms/p/1797528.html
Copyright © 2011-2022 走看看