poj 3281 Dining 拆点网络流
2016-02-25 21:16
555 查看
题目链接:http://poj.org/problem?id=3281
题意:
有N头牛,F种食物和D种饮料。
给出每头牛喜欢的一些食物和饮料。
每种饮料只能被分配给一只牛;每种食物也只能被分配给一只牛。
求能同时分配到食物和饮料的牛的最大数量。
思路:
设立一个超级源点和超级汇点。
超级源点向每个饮料连一条边,容量为1,代表每个饮料只能被分配一次。
每个食物向超级汇点连一条边,容量为1,代表每个食物只能被分配一次。
把每头牛拆分为2个点i和i',i向i’连边,容量为1。
把饮料和喜欢它的牛i连边,容量为1。
把牛i'向每个它喜欢的食物连边,容量为1。
最后求最大流。
拆点适用于一个点需要使用多次的情况以及有限制结点容量的情况。
对于一个点需要使用多次的情况,一般情况下,拆分后连一条边,容量为1。
对于限制结点容量的情况,把原始结点u分裂成u1和u2两个结点,中间连接一条有向弧,容量 = u的结点容量。
题意:
有N头牛,F种食物和D种饮料。
给出每头牛喜欢的一些食物和饮料。
每种饮料只能被分配给一只牛;每种食物也只能被分配给一只牛。
求能同时分配到食物和饮料的牛的最大数量。
思路:
设立一个超级源点和超级汇点。
超级源点向每个饮料连一条边,容量为1,代表每个饮料只能被分配一次。
每个食物向超级汇点连一条边,容量为1,代表每个食物只能被分配一次。
把每头牛拆分为2个点i和i',i向i’连边,容量为1。
把饮料和喜欢它的牛i连边,容量为1。
把牛i'向每个它喜欢的食物连边,容量为1。
最后求最大流。
拆点适用于一个点需要使用多次的情况以及有限制结点容量的情况。
对于一个点需要使用多次的情况,一般情况下,拆分后连一条边,容量为1。
对于限制结点容量的情况,把原始结点u分裂成u1和u2两个结点,中间连接一条有向弧,容量 = u的结点容量。
//#include <bits/stdc++.h> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <queue> using namespace std; int n, m, s, t; #define maxn 410 #define inf 0x3f3f3f3f struct Edge { int from, to, cap, flow; Edge(int f, int t, int c, int fl) { from = f; to = t; cap = c; flow = fl; } }; vector <Edge> edges; vector <int> G[maxn]; int d[maxn], vis[maxn], cur[maxn]; void AddEdge(int from, int to, int cap) { edges.push_back(Edge(from, to, cap, 0)); edges.push_back(Edge(to, from, 0, 0)); m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool bfs() { memset(vis, 0, sizeof(vis)); d[s] = 0; vis[s] = 1; queue <int> q; q.push(s); while(!q.empty()) { int x = q.front(); q.pop(); for(int i = 0; i < G[x].size(); i++) { Edge &e = edges[G[x][i]]; if(!vis[e.to] && e.cap > e.flow) { d[e.to] = d[x] + 1; vis[e.to] = 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[e.to] == d[x] + 1 && (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 flow = 0; while(bfs()) { memset(cur, 0, sizeof(cur)); flow += dfs(s, inf); } return flow; } int N, F, D; int main() { // freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); while(~scanf("%d%d%d", &N, &F, &D)) { edges.clear(); for(int i = 0; i <= 2*N+F+D+1; i++) G[i].clear(); s = 0; t = F+2*N+D+1; n = F+2*N+D+2; for(int i = 1; i <= F; i++) AddEdge(s, i, 1); for(int i = 1; i <= D; i++) AddEdge(F+2*N+i, t, 1); for(int i = 1; i <= N; i++) AddEdge(F+i, F+N+i, 1); for(int i = 1; i <= N; i++) { int f, d; scanf("%d%d", &f, &d); int temp; while(f--) { scanf("%d", &temp); AddEdge(temp, F+i, 1); } while(d--) { scanf("%d", &temp); AddEdge(F+N+i, F+2*N+temp, 1); } } int flow = maxflow(); printf("%d\n", flow); } return 0; }
相关文章推荐
- 李望 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-10000290
- HDU1532 - Drainage Ditches(网络流)
- 网络编程_UDP编程原理_发送类型_cs与bs区别JAVA187-188
- HTTP协议
- Android开发之旅:组件生命周期(一)出处:http://www.cnblogs.com/skynet/
- HDU3549 - Flow Problem(模板网络流 + Ford-Fulkerson算法)
- poj 1459 Power Network 多源多汇网络流
- 人工神经网络训练样本的选择方法
- Http状态码说明
- lighttpd-1.4.39 : mod_staticfile
- HTTP协议中,GET方法与POST方法比较
- The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
- linux网络编程之shutdown() 与 close()函数详解
- iptables实现网络防火墙及地址转换
- iptables实现网络防火墙及地址转换
- tcp三次握手和time wait --- 转
- SSL中间人监测关键技术---SSL会话劫持
- HTTP相关
- iOS-原生网络请求
- 上下界网络流学习小记