网络流题有Dinic板子还正是爽啊 ≥v≤~2333

 

首先我们把一个数字拆成2个点,连边规则:

(1)S向i连权为a[i]的边,i + n向T连权为a[i]的边

(2)有关系的点互相连边,权为inf

则答案是sigma(a[i]) - 最小割值

 

  1 /**************************************************************
  2     Problem: 3275
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:1560 ms
  7     Memory:6760 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <cmath>
 12 #include <cstring>
 13 #include <algorithm>
 14  
 15 using namespace std;
 16 const int N = 6005;
 17 const int M = 500001;
 18 const int inf = (int) 1e9;
 19    
 20 struct edges{
 21     int next, to, f;
 22     edges() {}
 23     edges(int _next, int _to, int _f) : next(_next), to(_to), f(_f) {}
 24 } e[M];
 25  
 26 int n, m, ans, S, T;
 27 int first[N], tot = 1;
 28 int q[N], a[N >> 1], d[N];
 29  
 30 inline int read() {
 31     int x = 0;
 32     char ch = getchar();
 33     while (ch < '0' || '9' < ch)
 34         ch = getchar();
 35     while ('0' <= ch && ch <= '9') {
 36         x = x * 10 + ch - '0';
 37         ch = getchar();
 38     }
 39     return x;
 40 }
 41  
 42 inline void add_edge(int x, int y, int z){
 43     e[++tot] = edges(first[x], y, z);
 44     first[x] = tot;
 45 }
 46    
 47 inline void Add_Edges(int x, int y, int z){
 48     add_edge(x, y, z);
 49     add_edge(y, x, 0);
 50 }
 51    
 52 bool bfs(){
 53     memset(d, 0, sizeof(d));
 54     q[1] = S, d[S] = 1;
 55     int l = 0, r = 1, x, y;
 56     while (l < r){
 57         ++l;
 58         for (x = first[q[l]]; x; x = e[x].next){
 59             y = e[x].to;
 60             if (!d[y] && e[x].f)
 61                 q[++r] = y, d[y] = d[q[l]] + 1;
 62         }
 63     }
 64     return d[T];
 65 }
 66    
 67 int dinic(int p, int limit){
 68     if (p == T || !limit) return limit;
 69     int x, y, tmp, rest = limit;
 70     for (x = first[p]; x; x = e[x].next){
 71         y = e[x].to;
 72         if (d[y] == d[p] + 1 && e[x].f && rest){
 73             tmp = dinic(y, min(rest, e[x].f));
 74             rest -= tmp;
 75             e[x].f -= tmp, e[x ^ 1].f += tmp;
 76             if (!rest) return limit;
 77         }
 78     }
 79     if (limit == rest) d[p] = 0;
 80     return limit - rest;
 81 }
 82    
 83 int Dinic(){
 84     int res = 0, x;
 85     while (bfs())
 86         res += dinic(S, inf);
 87     return res;
 88 }
 89  
 90 int gcd(int a, int b) {
 91     return b ? gcd(b, a % b) : a;
 92 }
 93  
 94 inline int Sqr(int x) {
 95     return x * x;
 96 }
 97  
 98 inline bool check(int x, int y) {
 99     int t = x * x + y * y;
100     return Sqr(((int) sqrt(t))) == t && gcd(x, y) == 1;
101 }
102  
103 int main() {
104     int i, j;
105     n = read();
106     S = n << 1 | 1, T = S + 1;
107     for (i = 1; i <= n; ++i) {
108         a[i] = read();
109         Add_Edges(S, i, a[i]);
110         Add_Edges(i + n, T, a[i]);
111         ans += a[i];
112     }
113     for (i = 1; i <= n; ++i)
114         for (j = i + 1; j <= n; ++j)
115             if (check(a[i], a[j]))
116                 Add_Edges(i, j + n, inf), Add_Edges(j, i + n, inf);
117     printf("%d\n", ans - Dinic() / 2);
118     return 0;
119 }
View Code

 

posted on 2014-11-17 18:02  Xs酱~  阅读(224)  评论(3编辑  收藏  举报