UVALive - 3268 Jamie's Contact Groups(二分+最大流)
2015-08-25 00:33
477 查看
题目大意:有n个人和m个组,一个人可能属于多个组,现在请你从某些组中去掉几个人,使得每个人都只属于一个组,且人数最多的组中人员数目达到最小
解题思路:最大值最小化,二分
建图就比较简单了,二分主要二分组别到超级汇点的容量
解题思路:最大值最小化,二分
建图就比较简单了,二分主要二分组别到超级汇点的容量
[code]#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; #define N 2010 #define INF 0x3f3f3f3f struct Edge{ int from, to, cap, flow; Edge() {} Edge(int from, int to, int cap, int flow) : from(from), to(to), cap(cap), flow(flow) {} }; struct Dinic{ int n, m, s, t; vector<Edge> edges; vector<int> G ; bool vis ; int d , cur ; void init(int n) { this->n = n; for (int i = 0; i <= n; i++) { G[i].clear(); } edges.clear(); } void AddEdge(int from, int to, int cap) { edges.push_back(Edge(from, to, cap, 0)); edges.push_back(Edge(to, from, 0, 0)); int m = edges.size(); G[from].push_back(m - 2); G[to].push_back(m - 1); } bool BFS() { memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(s); vis[s] = 1; d[s] = 0; while (!Q.empty()) { int u = Q.front(); Q.pop(); for (int i = 0; i < G[u].size(); i++) { Edge &e = edges[G[u][i]]; if (!vis[e.to] && e.cap > e.flow) { vis[e.to] = true; d[e.to] = d[u] + 1; Q.push(e.to); } } } return vis[t]; } int DFS(int x, int a) { if (x == t || a == 0) return a; int flow = 0, f; for (int i = cur[x]; i < G[x].size(); i++) { Edge &e = edges[G[x][i]]; if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) { e.flow += f; edges[G[x][i] ^ 1].flow -= f; flow += f; a -= f; if (a == 0) break; } } return flow; } int Maxflow(int s, int t) { this->s = s; this->t = t; int flow = 0; while (BFS()) { memset(cur, 0, sizeof(cur)); flow += DFS(s, INF); } return flow; } bool MinCut(int mid, int m, int n, int source, int sink) { for (int i = 0; i < edges.size(); i++) edges[i].flow = 0; for (int i = 0; i < m; i++) for (int j = 0; j < G[i].size(); j++) if (edges[G[i][j]].to == sink) edges[G[i][j]].cap = mid; int t = Maxflow(source, sink); if (t == n) { return true; } return false; } }; Dinic dinic; int n, m, source, sink; int num , Max; char name[30]; void init() { source = n + m; sink = source + 1; memset(num, 0, sizeof(num)); dinic.init(sink); Max = -INF; int t; char c; for (int i = 0; i < n; i++) { dinic.AddEdge(source, m + i, 1); scanf("%s", name); c = getchar(); while (c != '\n') { scanf("%d", &t); dinic.AddEdge(m + i, t, 1); num[t]++; c = getchar(); } } for (int i = 0; i < m; i++) { Max = max(Max, num[i]); dinic.AddEdge(i, sink, num[i]); } } void solve() { // printf("Max is %d\n", Max); int l = 0, r = Max, mid, ans = 0; while (l <= r) { mid = (l + r) / 2; if (dinic.MinCut(mid, m, n, source, sink)) { r = mid - 1; ans = mid; } else l = mid + 1; } printf("%d\n", ans); } int main() { while (scanf("%d%d", &n, &m) != EOF && n + m) { init(); solve(); } return 0; }
相关文章推荐
- cs193P assignmentV 问题1
- cocos2d-x改进的粒子系统和编辑器(需求分析)
- 想写一个网络游戏(PS:纯粹是为了好玩)
- 【DirectX 2D游戏编程基础】directx 精灵绘图的应用,锚点与变换
- UVA - 11082 Matrix Decompressing(最大流+行列模型)
- 华为机试题:字符串最后一个单词的长度
- ReactJS入门学习二
- TCP建立和解除连接过程
- php动态调用函数方法&&非关系数据库的优势
- php动态调用函数方法&&非关系数据库的优势
- Vim按Esc后光标左移问题的解决
- Oracle设置表中自增字段
- Android 自定义主菜单
- 【ZOJ2334】Monkey King
- c++ 构造函数初始化列表
- thinkinginjava学习笔记01_导论
- 分配内存时如何减少内存碎片(四)
- 分配内存时如何减少内存碎片(三)
- 分配内存时如何减少内存碎片(二)
- 分配内存时如何减少内存碎片(一)