bzoj 3275 最小割
给你一堆东西,叫你选一些东西出来,使得价值最大,要求选出的东西集合中的任意a,b满足性质p。
可以考虑:
1、拟阵?
2、二分图?
这道题由于数学硬伤,不知道不存在两条直角边是奇数,斜边是整数的直角三角形。
证明是:
对于奇数a: a*a = 1 mod 4
对于偶数a: a*a = 0 mod 4
所以对于两个奇数a,b: a*a+b*b = 2 mod 4
不存在整数c使得: a*a+b*b = c*c mod 4
1 /************************************************************** 2 Problem: 3275 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:3616 ms 7 Memory:1176 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cmath> 12 #include <cstring> 13 #include <vector> 14 #define min(a,b) ((a)<(b)?(a):(b)) 15 #define oo 0x3f3f3f3f 16 #define N 6010 17 using namespace std; 18 19 typedef long long dnt; 20 struct Edge { 21 int u, v, f; 22 Edge( int u, int v, int f ):u(u),v(v),f(f){} 23 }; 24 struct Dinic { 25 int src, dst; 26 vector<Edge> edge; 27 vector<int> g[N]; 28 int dep[N], cur[N], qu[N], bg, ed; 29 void init( int src, int dst ) { 30 this->src = src; 31 this->dst = dst; 32 } 33 void adde( int u, int v, int f ) { 34 g[u].push_back( edge.size() ); 35 edge.push_back( Edge(u,v,f) ); 36 g[v].push_back( edge.size() ); 37 edge.push_back( Edge(v,u,0) ); 38 } 39 bool bfs() { 40 memset( dep, 0, sizeof(dep) ); 41 qu[bg=ed=1] = src; 42 dep[src] = 1; 43 while( bg<=ed ) { 44 int u=qu[bg++]; 45 for( int t=0; t<g[u].size(); t++ ) { 46 Edge &e = edge[g[u][t]]; 47 if( e.f && !dep[e.v] ) { 48 dep[e.v] = dep[e.u] + 1; 49 qu[++ed] = e.v; 50 } 51 } 52 } 53 return dep[dst]; 54 } 55 int dfs( int u, int a ) { 56 if( u==dst || a==0 ) return a; 57 int remain=a, past=0, na; 58 for( int &t=cur[u]; t<g[u].size(); t++ ) { 59 Edge &e=edge[g[u][t]]; 60 Edge &ve=edge[g[u][t]^1]; 61 if( e.f && dep[e.v]==dep[e.u]+1 && (na=dfs(e.v,min(remain,e.f))) ) { 62 remain -= na; 63 past += na; 64 e.f -= na; 65 ve.f += na; 66 if( !remain ) break; 67 } 68 } 69 return past; 70 } 71 int maxflow() { 72 int rt=0; 73 while( bfs() ) { 74 memset( cur, 0, sizeof(cur) ); 75 rt += dfs(src,oo); 76 } 77 return rt; 78 } 79 }D; 80 81 int n; 82 int src, dst; 83 int aa[N], sum; 84 int gcd( int a, int b ) { 85 return b ? gcd(b,a%b) : a; 86 } 87 bool ok( int a, int b ) { 88 if( gcd(a,b)!=1 ) return false; 89 dnt cc = (dnt)a*a + (dnt)b*b; 90 dnt c = (dnt)sqrt(cc); 91 if( c*c!=cc && (c+1)*(c+1)!=cc ) return false; 92 return true; 93 } 94 int main() { 95 scanf( "%d", &n ); 96 src = n+1, dst = n+2; 97 D.init( src, dst ); 98 for( int i=1; i<=n; i++ ) { 99 scanf( "%d", aa+i ); 100 sum += aa[i]; 101 if( aa[i]&1 ) 102 D.adde( src, i, aa[i] ); 103 else 104 D.adde( i, dst, aa[i] ); 105 } 106 for( int i=1; i<=n; i++ ) { 107 if( !(aa[i]&1) ) continue; 108 for( int j=1; j<=n; j++ ) { 109 if( aa[j]&1 ) continue; 110 if( !ok(aa[i],aa[j]) ) continue; 111 D.adde( i, j, oo ); 112 } 113 } 114 printf( "%d\n", sum-D.maxflow() ); 115 }