首页 > 代码库 > BZOJ 3158: 千钧一发

BZOJ 3158: 千钧一发

3158: 千钧一发

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 1201  Solved: 446
[Submit][Status][Discuss]

Description

 

Input

第一行一个正整数N。

第二行共包括N个正整数,第 个正整数表示Ai。

第三行共包括N个正整数,第 个正整数表示Bi。

 

Output

共一行,包括一个正整数,表示在合法的选择条件下,可以获得的能量值总和的最大值。

 

Sample Input



4
3 4 5 12
9 8 30 9

Sample Output


39

HINT

 



1<=N<=1000,1<=Ai,Bi<=10^6

 

Source

Katharon+#1

[Submit][Status][Discuss]

 

网络流求最小割,很机智的建图方式。

 

发现可以把数字按照奇偶性分类,奇数一定满足1条件,偶数一定满足2条件,WOC,然后就二分图了?

暴力判断奇数和偶数是否不能在同一集合中,如不能在同一集合,在其中加一天正无穷的边,表示不可割。

其余点按奇偶性分别向S,T连bi的边即可,Σbi - 最小割就是最终答案。

 

  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         scanf("%d", b + 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 3158: 千钧一发