【NOIP考前题目回顾】Luogu P1001
2017-10-29 19:54
218 查看
思路
最大流。建一个超级源点和超级汇点,然后从源点连出两条边,流量分别为a和b,最后将这两个定点分别向汇点连一条流量为无穷大的边,求得的最大流即为答案。代码
#include <cctype> #include <climits> #include <cstdio> #include <cstring> #include <iostream> #include <queue> #define BLA(X) int X[100001] = { 0 } BLA(HEAD); BLA(NEX); BLA(PRE); BLA(V); BLA(USED); bool VIS[100001] = { 0 }; BLA(LIS); int S, T; int tot = 0; void INS(const int x, const int y, const int v) { tot++; LIS[tot] = y; NEX[tot] = HEAD[x]; HEAD[x] = tot; V[tot] = v; } void INSERT(const int x, const int y, const int v) { INS(x, y, v); INS(y, x, 0); } bool bfs(const int S) { std::queue<int> q; q.push(S); std::memset(PRE, 0xff, sizeof PRE); PRE[S] = 1; while (!q.empty()) { int x = q.front(); q.pop(); for (int t = HEAD[x]; t; t = NEX[t]) if (PRE[LIS[t]] == -1 && V[t]) { PRE[LIS[t]] = PRE[x] + 1; q.push(LIS[t]); } } if (PRE[T] == -1) return false; return true; } int dfs(const int pos, const int flow) { if (pos == T) return flow; int w, t, used = 0; for (int t = HEAD[pos]; t; t = NEX[t]) { if (V[t] && PRE[LIS[t]] == PRE[pos] + 1) { w = dfs(LIS[t], std::min(flow - used, V[t])); used += w; V[t] -= w; V[t + 1] += w; if (used == flow) return flow; } } if (!used) PRE[pos] = -1; return used; } int DINIC(const int S) { int ans = 0; while (bfs(S)) ans += dfs(S, INT_MAX); return ans; } int main(int argc, char **argv) { int x, y; std::cin >> x >> y; INSERT(1, 2, x); INSERT(1, 3, y); INSERT(2, 4, x); INSERT(3, 4, y); S = 1; T = 4; std::cout << DINIC(1) << std::endl; #ifdef __EDWARD_EDIT std::cin.get(); std::cin.get(); #endif return 0; }
相关文章推荐
- 【NOIP考前题目回顾】Luogu P1005
- 【NOIP考前题目回顾】Luogu P1012
- 【NOIP考前题目回顾】Luogu P1000
- 【NOIP考前题目回顾】Luogu P1003
- 【NOIP考前题目回顾】Luogu P1040
- 【NOIP考前题目回顾】Luogu P1046
- 【NOIP考前题目回顾】Luogu P1005
- 【NOIP考前题目回顾】Luogu P1006
- 【NOIP考前题目回顾】Luogu P1047
- NOIP考前的心得体会
- Java基础 IO回顾 题目
- 题目:[NOIP2010普及组]三国游戏
- 题目:[NOIP2003]加分二叉树
- NOIP2010提高组初赛(答案+选择题题目+个人分析)
- NOIP历年题目分析
- NOIP2017考前复习
- NOIP系列复习及题目集合
- NOIP2000题目汇总
- NOIP2015考前模拟!!!
- 一个liunx命令题目引发的对shell的回顾