The main topic: Your phone Address book has n contacts, m groups, which, some of the contacts in multiple groups. Your task is to delete some of the contacts in some groups so that each contact is in only one group and the fewest number of people in the group. Find out the number of people in the group with the largest number.
Title Analysis: Required is the smallest maximum, two-minute enumeration of this minimum maximum number of x. Increase the source point S and the meeting point T, an arc from S to each contact, with a capacity of 1, indicating that a contact can only be in one group, and then an arc for each contact to his group, with a capacity of 1, indicating that the contact is saved at most once in the group, and then an arc is attached to the sink point from each grouping, and the capacity is X. Indicates that this group cannot save more than X contacts. The maximum flow, if each edge of the source point S is loaded, indicates that X is feasible.
The code is as follows:
# include<iostream># include<cstdio># include<cmath># include<string># include<vector ># include<list># include<set># include<map># include<queue># include<cstring># Include<algorithm>using namespace std;# define LL long long# define REP (i,s,n) for (int i=s;i<n;++i) # define CL (A, b) memset (A,b,sizeof (a)) # define CLL (A,b,n) Fill (a,a+n,b) const double inf=1e30;const int Inf=1<<30;const int n= 1505;struct edge{int FR,TO,CAP,FW; Edge (int _fr,int _to,int _cap,int _fw): fr (_fr), to (_to), Cap (_CAP), FW (_FW) {}};vector<edge>edges,tedges;vector <int>g[n];int cur[n],vis[n],d[n],mark[505];void init (int N) {edges.clear (); REP (I,0,n) g[i].clear ();} void Addedge (int u,int v,int cap) {Edges.push_back (Edge (u,v,cap,0)); Edges.push_back (Edge (v,u,0,0)); int m=edges.size (); G[u].push_back (m-2); G[v].push_back (m-1);} BOOL BFS (int s,int t) {CL (vis,0); Vis[s]=1; d[s]=0; queue<int>q; Q.puSH (s); while (!q.empty ()) {int U=q.front (); Q.pop (); REP (I,0,g[u].size ()) {Edge &e=edges[G[u][i]]; if (!VIS[E.TO]&&E.CAP>E.FW) {d[e.to]=d[u]+1; Vis[e.to]=1; Q.push (e.to); }}} return vis[t];} int DFS (int u,int t,int a) {if (u==t| | a==0) return A; int flow=0,f; for (int &i=cur[u];i<g[u].size (); ++i) {Edge &e=edges[G[u][i]]; if (d[e.to]==d[u]+1&& (F=dfs (E.to,t,min (A,E.CAP-E.FW))) >0) {e.fw+=f; Edges[g[u][i]^1].fw-=f; Flow+=f; A-=f; if (a==0) break; }} return flow;} int dinic (int s,int t) {int flow=0; while (BFS (s,t)) {CL (cur,0); Flow+=dfs (S,t,inf); } return flow;} BOOL Read (int &x) {x=0; char c; while (C=getchar ()) {if (c== ') return true; else if (c== ' \ n ') return false; else x=x*10+c-' 0 '; }}bool JUDGE () {REP (I,0,g[0].size ()) if (EDGES[G[0][I]].CAP>0&&EDGES[G[0][I]].CAP!=EDGES[G[0][I]].FW) return Fals E return true;} int main () {int n,m; Char name[20]; while (scanf ("%d%d", &n,&m) && (n+m)) {init (n+m+2); CL (mark,0); REP (i,1,n+1) {cin>>name; Addedge (0,m+i,1); int A; GetChar (); while (read (a)) {++mark[a]; Addedge (m+i,a+1,1); } addedge (m+i,a+1,1); ++mark[a]; } int cnt=edges.size (); Tedges.clear (); REP (i,0,cnt) tedges.push_back (Edges[i]); int l=0,r=0; REP (i,0,m) R=max (R,mark[i]); while (l<r) {int mid=l+ (R-L)/2; Init (n+m+2); REP (i,0,cnt) Addedge (TEDGES[I].FR,TEDGES[I].TO,TEDGES[I].CAP); REP (i,0,m) if (Mark[i]) Addedge (I+1,n+m+1,min (Mid,mark[i])); Dinic (0,n+m+1); if (Judge ()) R=mid; else l=mid+1; } printf ("%d\n", L); } return 0;}
UVALive-3268 Jamie's contact Groups (maximum flow, network flow modeling)