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
原文地址:https://www.cnblogs.com/sxprovence/p/5116299.html