UVA - 10779 Collectors Problem(最大流)
2015-08-25 00:04
211 查看
题目大意:有N个人在收集贴纸。现在给出每个人所拥有的贴纸
然后1这个想要得到更多种类的贴纸,所以他要拿他的贴纸去跟别人换,换的条件是1张交换1张,且你所交换的那张贴纸的种类对方没有,你想要得到的贴纸的种类对方至少有2张,问最后这个人能得到多少种贴纸
解题思路:一个超级源点,连接贴纸的种类,容量为1这个人所拥有的该种类的贴纸数量
将所有贴纸的种类连接到超级汇点,容量为1
在弄出N-1个点,代表另外的人,如果该贴纸的种类对方没有,那么连边,容量为1,因为只需要1张就够了(贴纸 –>人)
如果该贴纸对方有至少两张,那么连边,容量为这个人的该贴纸的数量-1(至少要保留一张,人–>贴纸)
然后跑最大流
然后1这个想要得到更多种类的贴纸,所以他要拿他的贴纸去跟别人换,换的条件是1张交换1张,且你所交换的那张贴纸的种类对方没有,你想要得到的贴纸的种类对方至少有2张,问最后这个人能得到多少种贴纸
解题思路:一个超级源点,连接贴纸的种类,容量为1这个人所拥有的该种类的贴纸数量
将所有贴纸的种类连接到超级汇点,容量为1
在弄出N-1个点,代表另外的人,如果该贴纸的种类对方没有,那么连边,容量为1,因为只需要1张就够了(贴纸 –>人)
如果该贴纸对方有至少两张,那么连边,容量为这个人的该贴纸的数量-1(至少要保留一张,人–>贴纸)
然后跑最大流
[code]#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; #define N 1010 #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; } }; Dinic dinic; int n, m, source, sink, cas = 1; int num[15][30]; void init() { scanf("%d%d", &n, &m); memset(num, 0, sizeof(num)); source = 0; sink = n + m; int x, y; for (int i = 1; i <= n; i++) { scanf("%d", &x); for (int j = 1; j <= x; j++) { scanf("%d", &y); num[i][y]++; } } dinic.init(sink); for (int j = 1; j <= m; j++) { dinic.AddEdge(source, j, num[1][j]); dinic.AddEdge(j, sink, 1); } for (int i = 2; i <= n; i++) for (int j = 1; j <= m; j++) { if (num[i][j] > 1) dinic.AddEdge(m + i - 1, j, num[i][j] - 1); if (!num[i][j]) dinic.AddEdge(j, m + i - 1, 1); } int ans = dinic.Maxflow(source, sink); printf("Case #%d: %d\n", cas++, ans); } int main() { int test; scanf("%d", &test); while (test--) { init(); } return 0; }
相关文章推荐
- Java序列化Serializable和Externalizable
- 08/23 总结
- HDU5396 Expressions(区间DP)
- 【C语言】预处理指令—文件包含
- 14个顶级开发社区
- XML解析
- 08/23 总结
- 使用Python的Bottle框架写一个简单的服务接口的示例
- 百度地图API使用方法详解
- 基于PHP+jQuery+MySql实现红蓝(顶踩)投票代码
- mybatis的动态sql详解(精)
- 基于jquery实现select选择框内容左右移动添加删除代码分享
- jQuery实现点击小图显示大图代码分享
- jQuery+CSS实现的网页二级下滑菜单效果
- jquery实现的3D旋转木马特效代码分享
- jquery实现在网页指定区域显示自定义右键菜单效果
- jquery图片滚动放大代码分享
- JS+CSS实现滑动切换tab菜单效果
- jQuery合作伙伴左右滚动特效
- js文本框走动跑马灯效果代码分享