BZOJ2661 [BeiJing wc2012]连连看
2014-12-21 17:18
381 查看
把每个数拆成两个点建图
具体原因我想了想。。。因为一个点一定是不能做的。。。但是两个点不能保证一定是对称流法啊。。。(坑)
如果两个数a, b满足要求,则a -> b', b -> a',边流量为1,费用为- a - b
最后再建源汇S, T,分别连边,流量为1,费用为0
跑一边费用流即可,但是要记下流量
View Code
具体原因我想了想。。。因为一个点一定是不能做的。。。但是两个点不能保证一定是对称流法啊。。。(坑)
如果两个数a, b满足要求,则a -> b', b -> a',边流量为1,费用为- a - b
最后再建源汇S, T,分别连边,流量为1,费用为0
跑一边费用流即可,但是要记下流量
/************************************************************** Problem: 2661 User: rausen Language: C++ Result: Accepted Time:128 ms Memory:3984 kb ****************************************************************/ #include <cstdio> #include <cmath> #include <algorithm> using namespace std; const int N = 2005; const int M = N * 100; const int inf = (int) 1e9; struct edges { int next, to, f, cost; edges() {} edges(int _n, int _t, int _f, int _c) : next(_n), to(_t), f(_f), cost(_c) {} } e[M]; int n, S, T; int first , tot = 1; int d , g , q ; bool v ; inline void Add_Edges(int x, int y, int f, int c) { e[++tot] = edges(first[x], y, f, c), first[x] = tot; e[++tot] = edges(first[y], x, 0, -c), first[y] = tot; } inline int calc() { int flow = inf, x; for (x = g[T]; x; x = g[e[x ^ 1].to]) flow = min(flow, e[x].f); for (x = g[T]; x; x = g[e[x ^ 1].to]) e[x].f -= flow, e[x ^ 1].f += flow; return flow; } bool spfa() { int x, y, l, r; for (x = 1; x <= T; ++x) d[x] = inf; d[S] = 0, v[S] = 1, q[0] = S; for(l = r = 0; l != (r + 1) % N; ++l %= N) { for (x = first[q[l]]; x; x = e[x].next) if (d[q[l]] + e[x].cost < d[y = e[x].to] && e[x].f) { d[y] = d[q[l]] + e[x].cost, g[y] = x; if (!v[y]) q[++r %= N] = y, v[y] = 1; } v[q[l]] = 0; } return d[T] != inf; } inline void work() { int ans1 = 0, ans2 = 0, del; while (spfa()) { del = calc(); ans1 += del, ans2 += del * d[T]; } printf("%d %d\n", ans1 >> 1, -ans2 >> 1); } inline int sqr(int x) { return x * x; } inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; } inline bool check(int a, int b) { int t = sqr(b) - sqr(a); if (sqr((int) sqrt(t)) != t) return 0; return gcd(a, (int) sqrt(t)) == 1; } int main() { int a, b, i, j; scanf("%d%d", &a, &b); S = (b - a + 1) << 1 | 1, T = S + 1; for (i = a; i <= b; ++i) for (j = a; j < i; ++j) if (check(j, i)) Add_Edges(i - a + 1, j + b - a * 2 + 2, 1, - i - j), Add_Edges(j - a + 1, i + b - a * 2 + 2, 1, - i - j); for (i = a; i <= b; ++i) Add_Edges(S, i - a + 1, 1, 0), Add_Edges(i + b - a * 2 + 2, T, 1, 0); work(); return 0; }
View Code
相关文章推荐
- BZOJ 2661([BeiJing wc2012]连连看-费用流)
- 【BZOJ】【2661】【Beijing WC2012】连连看
- 【 bzoj 2661 】 [BeiJing wc2012]连连看 - 拆点费用流
- BZOJ【bzoj2661】[BeiJing wc2012]连连看
- 【费用流】bzoj2661 [BeiJing wc2012]连连看
- 【bzoj2661】[BeiJing wc2012]连连看 最大费用最大流
- 【BeiJing wc2012】【BZOJ2661】连连看
- BZOJ_2661_[BeiJing wc2012]连连看_费用流
- 【bzoj2661】【BeiJing wc2012】【连连看】【费用流】
- BZOJ 2661 [BeiJing wc2012]连连看 费用流
- [BZOJ2661][BeiJing wc2012]连连看 费用流
- bzoj2661 [BeiJing wc2012]连连看(拆点费用流)
- 【BZOJ2661】[BeiJing wc2012]连连看 最大费用流
- bzoj 2661: [BeiJing wc2012]连连看
- bzoj2668 [BeiJing wc2012]连连看
- BZOJ2661 / wc2012 连连看【费用流】
- [BZOJ]2661: [BeiJing wc2012]连连看 费用流
- BZOJ 2661: [BeiJing wc2012]连连看( 费用流 )
- BZOJ 2661: [BeiJing wc2012]连连看(简单费用流)
- bzoj2661:[BeiJing wc2012]连连看——费用流 + 拆点