BZOJ2661 [BeiJing wc2012]连连看

把每个数拆成两个点建图

具体原因我想了想。。。因为一个点一定是不能做的。。。但是两个点不能保证一定是对称流法啊。。。(坑)

如果两个数a, b满足要求,则a -> b', b -> a',边流量为1,费用为- a - b

最后再建源汇S, T,分别连边,流量为1,费用为0

跑一边费用流即可,但是要记下流量

 1 /**************************************************************
 2     Problem: 2661
 3     User: rausen
 4     Language: C++
 5     Result: Accepted
 6     Time:128 ms
 7     Memory:3984 kb
 8 ****************************************************************/
 9  
10 #include <cstdio>
11 #include <cmath>
12 #include <algorithm>
13  
14 using namespace std;
15 const int N = 2005;
16 const int M = N * 100;
17 const int inf = (int) 1e9;
18  
19 struct edges {
20     int next, to, f, cost;
21     edges() {}
22     edges(int _n, int _t, int _f, int _c) : next(_n), to(_t), f(_f), cost(_c) {}
23 } e[M];
24   
25 int n, S, T;
26 int first[N], tot = 1;
27 int d[N], g[N], q[N];
28 bool v[N];
29  
30    
31 inline void Add_Edges(int x, int y, int f, int c) {
32     e[++tot] = edges(first[x], y, f, c), first[x] = tot;
33     e[++tot] = edges(first[y], x, 0, -c), first[y] = tot;
34 }
35   
36 inline int calc() {
37     int flow = inf, x;
38     for (x = g[T]; x; x = g[e[x ^ 1].to])
39         flow = min(flow, e[x].f);
40     for (x = g[T]; x; x = g[e[x ^ 1].to])
41         e[x].f -= flow, e[x ^ 1].f += flow;
42     return flow;
43 }
44   
45 bool spfa() {
46     int x, y, l, r;
47     for (x = 1; x <= T; ++x)
48         d[x] = inf;
49     d[S] = 0, v[S] = 1, q[0] = S;
50     for(l = r = 0; l != (r + 1) % N; ++l %= N) {
51         for (x = first[q[l]]; x; x = e[x].next)
52             if (d[q[l]] + e[x].cost < d[y = e[x].to] && e[x].f) {
53                 d[y] = d[q[l]] + e[x].cost, g[y] = x;
54                 if (!v[y])
55                     q[++r %= N] = y, v[y] = 1;
56             }
57         v[q[l]] = 0;
58     }
59     return d[T] != inf;
60 }
61  
62 inline void work() {
63     int ans1 = 0, ans2 = 0, del;
64     while (spfa()) {
65         del = calc();
66         ans1 += del, ans2 += del * d[T];
67     }
68     printf("%d %d
", ans1 >> 1, -ans2 >> 1);
69 }
70  
71 inline int sqr(int x) {
72     return x * x;
73 }
74  
75 inline int gcd(int a, int b) {
76     return b ? gcd(b, a % b) : a;
77 }
78  
79 inline bool check(int a, int b) {
80     int t = sqr(b) - sqr(a);
81     if (sqr((int) sqrt(t)) != t) return 0;
82     return gcd(a, (int) sqrt(t)) == 1;
83 }
84  
85 int main() {
86     int a, b, i, j;
87     scanf("%d%d", &a, &b);
88     S = (b - a + 1) << 1 | 1, T = S + 1;
89     for (i = a; i <= b; ++i)
90         for (j = a; j < i; ++j) if (check(j, i))
91             Add_Edges(i - a + 1, j + b - a * 2 + 2, 1, - i - j),
92             Add_Edges(j - a + 1, i + b - a * 2 + 2, 1, - i - j);
93     for (i = a; i <= b; ++i)
94         Add_Edges(S, i - a + 1, 1, 0), Add_Edges(i + b - a * 2 + 2, T, 1, 0);
95     work();
96     return 0;
97 }
View Code
By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
原文地址:https://www.cnblogs.com/rausen/p/4176791.html