首页 > 代码库 > BZOJ 3275: Number

BZOJ 3275: Number

3275: Number

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 874  Solved: 371
[Submit][Status][Discuss]

Description

有N个正整数,需要从中选出一些数,使这些数的和最大。
若两个数a,b同时满足以下条件,则a,b不能同时被选
1:存在正整数C,使a*a+b*b=c*c
2:gcd(a,b)=1

Input

第一行一个正整数n,表示数的个数。
第二行n个正整数a1,a2,?an。
 
 

Output

最大的和。
 

Sample Input

5
3 4 5 6 7



Sample Output

22


HINT

 

n<=3000。

 

Source

网络流

[Submit][Status][Discuss]

 

机制建图,同 BZOJ 3158: 千钧一发 。

 

  1 #include <cmath>  2 #include <cstdio>  3 #include <cstring>  4   5 typedef long long lnt;  6   7 const int siz = 1000005;  8 const int inf = 1000000007;  9  10 int n; 11 int a[siz]; 12 int b[siz]; 13  14 int tot; 15 int s, t; 16 int hd[siz]; 17 int to[siz]; 18 int fl[siz]; 19 int nt[siz]; 20  21 inline void add(int u, int v, int f) 22 { 23     nt[tot] = hd[u]; to[tot] = v; fl[tot] = f; hd[u] = tot++; 24     nt[tot] = hd[v]; to[tot] = u; fl[tot] = 0; hd[v] = tot++; 25 } 26  27 int dep[siz]; 28  29 inline bool bfs(void) 30 { 31     static int que[siz]; 32     static int head, tail; 33  34     memset(dep, 0, sizeof(dep)); 35     head = 0, tail = 0; 36     que[tail++] = s; 37     dep[s] = 1; 38  39     while (head != tail) 40     { 41         int u = que[head++], v; 42  43         for (int i = hd[u]; ~i; i = nt[i]) 44             if (!dep[v = to[i]] && fl[i]) 45                 dep[que[tail++] = v] = dep[u] + 1; 46     } 47  48     return dep[t]; 49 } 50  51 int cur[siz]; 52  53 int min(int a, int b) 54 { 55     return a < b ? a : b; 56 } 57  58 int dfs(int u, int f) 59 { 60     if (u == t || !f) 61         return f; 62          63     int used = 0, flow, v; 64  65     for (int i = cur[u]; ~i; i = nt[i]) 66         if (dep[v = to[i]] == dep[u] + 1 && fl[i]) 67         { 68             flow = dfs(v, min(f - used, fl[i])); 69              70             used += flow; 71             fl[i] -= flow; 72             fl[i^1] += flow; 73  74             if (used == f) 75                 return f; 76  77             if (fl[i]) 78                 cur[u] = i; 79         } 80  81     if (!used) 82         dep[u] = 0; 83  84     return used; 85 } 86  87 inline int maxFlow(void) 88 { 89     int maxFlow = 0, newFlow; 90  91     while (bfs()) 92     { 93         for (int i = s; i <= t; ++i) 94             cur[i] = hd[i]; 95  96         while (newFlow = dfs(s, inf)) 97             maxFlow += newFlow; 98     } 99 100     return maxFlow;101 }102 103 inline lnt sqr(lnt x)104 {105     return x * x;106 }107 108 int gcd(int x, int y)109 {110     return y ? gcd(y, x % y) : x;111 }112 113 inline bool check(int x, int y)114 {115     if (gcd(x, y) != 1)116         return false;117 118     lnt t = sqr(x) + sqr(y);119     if (sqr(sqrt(t)) != t)120         return false;121 122     return true;123 }124 125 signed main(void)126 {127     scanf("%d", &n);128 129     for (int i = 1; i <= n; ++i)130         scanf("%d", a + i);131 132     for (int i = 1; i <= n; ++i)133         b[i] = a[i];134     135     s = 0, t = n + 1;136 137     memset(hd, -1, sizeof(hd));138 139     for (int i = 1; i <= n; ++i)140         if (a[i] & 1)141             add(s, i, b[i]);142         else143             add(i, t, b[i]);144 145     for (int i = 1; i <= n; ++i)146         for (int j = 1; j <= n; ++j)147             if (a[i] & 1)if (!(a[j] & 1))148                 if (check(a[i], a[j]))149                     add(i, j, inf);150 151     int sum = 0;152 153     for (int i = 1; i <= n; ++i)154         sum += b[i];155 156     printf("%d\n", sum - maxFlow());157 }

 

@Author: YouSiki

BZOJ 3275: Number