zoukankan      html  css  js  c++  java
  • POJ 2289 Jamie's Contact Groups (二分+最大流)

    题目大意:

    有n个人,可以分成m个组,现在给出你每个人可以去的组的编号,求分成的m组中人数最多的组最少可以有多少人。

    算法讨论:

    首先喷一下这题的输入,太恶心了。

    然后说算法:最多的最少,二分的字眼。二分什么,因为我们说的是组的人,所以要对组的流出量进行二分。其余的都连流量为1的边,然后对“小组”点的流出量二分连边,最后跑最大流判断

    是否等于N即可。还是蛮简单的。

    Codes:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <algorithm>
      5 #include <iostream>
      6 #include <vector>
      7 #include <queue>
      8 using namespace std;
      9 
     10 struct Edge{
     11     int from, to, cap, flow;
     12     Edge(int _from=0, int _to=0, int _cap=0, int _flow=0):
     13             from(_from), to(_to), cap(_cap), flow(_flow) {}
     14 }E[500000 + 5];
     15 
     16 struct Dinic{
     17     static const int N = 1500 + 5;
     18     static const int M = 1050000 + 5;
     19     static const int oo = 0x3f3f3f3f;
     20     
     21     int n, m, s, t;
     22     vector <Edge> edges;
     23     vector <int> G[N];
     24     int cur[N], dis[N];
     25     bool vi[N];
     26     
     27     void Clear(){
     28         for(int i = 0; i <= n; ++ i) G[i].clear();
     29         edges.clear();
     30     }
     31     void Add(int from, int to, int cap, int flow){
     32         edges.push_back((Edge){from, to, cap, 0});
     33         edges.push_back((Edge){to, from, 0, 0});
     34         int m = edges.size();
     35         G[from].push_back(m-2);
     36         G[to].push_back(m-1);
     37     }
     38     bool bfs(){
     39         memset(vi, false, sizeof vi);
     40         dis[s] = 0; vi[s] = true;
     41         queue <int> q;
     42         q.push(s);
     43         while(!q.empty()){
     44             int x = q.front(); q.pop();
     45             for(int i = 0; i < G[x].size(); ++ i){
     46                 Edge &e = edges[G[x][i]];
     47                 if(!vi[e.to] && e.cap > e.flow){
     48                     vi[e.to] = true;
     49                     dis[e.to] = dis[x] + 1;
     50                     q.push(e.to);
     51                 }
     52             }
     53         }
     54         return vi[t];
     55     }
     56     int dfs(int x, int a){
     57         if(x == t || a == 0) return a;
     58         int flw = 0, f;
     59         for(int &i = cur[x]; i < G[x].size(); ++ i){
     60             Edge &e = edges[G[x][i]];
     61             if(dis[x] + 1 == dis[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0){
     62                 e.flow += f; edges[G[x][i]^1].flow -= f;
     63                 a -= f; flw += f;
     64                 if(a == 0) break;
     65             }
     66         }
     67         return flw;
     68     }
     69     int MaxFlow(int s, int t){
     70         this->s = s; this->t = t;
     71         int flw = 0;
     72         while(bfs()){
     73             memset(cur, 0, sizeof cur);
     74             flw += dfs(s, oo);
     75         }
     76         return flw;
     77     }
     78 }Net;
     79 
     80 int n, m;
     81 char buf[5000];
     82 int len, cnt = 0, x, np;
     83 int bj[10000 + 5];
     84 int l, r, mid;
     85 
     86 bool check(int mv){
     87     Net.Clear();
     88     for(int i = 1; i <= n; ++ i)
     89         Net.Add(0, i, 1, 0);
     90     for(int i = 1; i <= cnt; ++ i)
     91         Net.Add(E[i].from, E[i].to, 1, 0);
     92     for(int i = n + 1; i <= n + m; ++ i)
     93         Net.Add(i, n + m + 1, mv, 0);
     94     return Net.MaxFlow(0, n + m + 1) == n;
     95 }
     96 
     97 void Solve(){
     98     int ans, l = 1;
     99     while(l <= r){
    100         mid = l + (r - l) / 2;
    101         if(check(mid)){
    102             ans = mid; r = mid - 1;
    103         }
    104         else l = mid + 1;
    105     }
    106     printf("%d
    ", ans);
    107     return;
    108 }
    109 int main(){
    110     
    111     while(scanf("%d%d", &n, &m) && n && m){
    112         cnt = 0;r = 0;
    113         memset(bj, 0, sizeof bj);
    114         Net.n = n + m + 1;
    115         for(int i = 1; i <= n; ++ i){
    116             getchar();gets(buf);
    117             len = strlen(buf);
    118             for(int j = 0; j < len;){
    119                 if(buf[j] < '0' || buf[j] > '9'){
    120                     j ++; continue;
    121                 }
    122                 while(buf[j] <= '9' && buf[j] >= '0'){
    123                     x = x * 10 + buf[j] - '0';j ++;
    124                 }
    125                 ++ cnt;
    126                 E[cnt] = (Edge){i, x + 1 + n, 0, 0};
    127                 bj[E[cnt].to] ++;
    128                 r = max(bj[E[cnt].to], r);
    129                 x = 0;
    130             }    
    131         }
    132         Solve();
    133     }
    134     return 0;
    135 }
    POJ 2289
  • 相关阅读:
    pandas的简单使用
    java搭建web从0-1(第一步:创建web工程)
    android通过命令行安装sdk
    iOS8不能通过itms-services协议下载安装app
    date命令转换日期命令提示date: illegal time format
    mac通过命令行获取证书和配置文件过期时间
    jenkin 不必要的Execute shell执行失败,导致jenkins都失败的解决
    命令行执行jenkins,构建job(可传递参数)
    Eclipse启动分析。。
    java非web应用修改 properties/xml配置文件后,无需重启应用即可生效---自动加载
  • 原文地址:https://www.cnblogs.com/sxprovence/p/5116299.html
Copyright © 2011-2022 走看看