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 }

时间: 2024-10-28 18:51:05

bzoj 3275 最小割的相关文章

BZOJ 1797 最小割

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1797 题意:给出一个有向图,每条边有流量,给出源点汇点s.t.对于每条边,询问:(1)是否存在一个最小割包含该边?(2)是否所有的最小割都包含该边? 思路:首先求最大流,在残余网络中求强连通 分量.对于每条原图中的边(最大流中添加的反向边不算)<u,v>,该边的残余流量为0且u和v在两个不同的强连通分量中,则存在一个最小割 包含该边:在上述满足且u与s在一个连通分量.v与t在一个连通

bzoj 3996 最小割

公式推出来后想了半天没思路,居然A是01矩阵..... 如果一个问题是求最值,并那么尝试先将所有可能收益加起来,然后矛盾部分能否用最小割表达(本题有两个矛盾,第一个是选还是不选,第二个是i,j有一个不选,就不能获得bij的收益). 1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #define N 510 5 #define S N+N*N 6 #define E S*10 7 #define

BZOJ - 1497 最小割应用

题意:基站耗费成本,用户获得利益(前提是投入成本),求最大获利 最小割的简单应用,所有可能的收益-(消耗的成本/失去的收益),无穷大边表示冲突,最小割求括号内的范围即可 #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<string> #in

BZOJ 2229 最小割

谁会像我一样把INF设成0x3f? GH Tree. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define maxv 250 #define maxe 50050 #define inf 0x7fffffff using namespace std; struct edge { int v,f,nxt; }

BZOJ 3275 Number &amp;&amp; 3158 千钧一发 最小割

题目大意:给出一些数字,要求选出一些数字并保证所有数字和最大,要求这其中的数字任意两个至少满足一个条件,则不能同时被选:1.这两个数的平方和是完全平方数.2.gcd(a,b) = 1. 思路:我们可以将奇数和偶数分开来讨论,奇数不满足1,偶数不满足2,所以奇数和奇数,偶数和偶数不会互相影响.之后O(n^2)的讨论其他数字对,有影响就连边,流量正无穷,最后跑最小割最最大获利. CODE: #define _CRT_SECURE_NO_WARNINGS #include <cmath> #incl

BZOJ 1266 上学路线route(最小割)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1266 题意:给出一个无向图,每条边有长度和代价.求出1到n的最短路.之后删掉一些边使得1到n的最短路变大?在此情况下使得删掉边的代价之和最小. 思路:首先求出每个点到1和n的最短路.之后可以确定每条边是否为关键边(就是最短路上的边).将关键边建立网络流图,求最小割即可. struct node { int v,cap,next; }; node edges[N]; int head[N

BZOJ 2007 海拔(平面图最小割-最短路)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2007 题意:给出一个n*n的格子,那么顶点显然有(n+1)*(n+1)个.每两个相邻顶点之间有两条边,这两条边是有向的,边上有权值..左上角为源点,右下角为汇点,求s到t的最小割. 思路:很明显这是一个平面图,将其转化为最 短路.我们将s到t之间连一条边,左下角为新图的源点S,右上角区域为新图的终点T,并且为每个格子编号.由于边是有向的,我们就要分析下这条边应该是哪 个点向哪个点的边.

BZOJ 1976 能量魔方 Cube(最小割)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1976 题意:给出一个n*n*n的立方体.每个小单位为字母P或者字母N.相邻两个小单位字母不同则总价值加1.现在有些小单位的字母已经确定,合理安排其他小单位的字母使得总价值最大? 思路:显然,若所有小单位都未确定,则进 行黑白染色即PN相间的安排时价值最大.基于这样的考虑,我们将所有小单位分成黑白两种颜色,设为A和B.显然同一种颜色之间是不会相邻的.设S集合为A 集合中的P(就是已经给出

BZOJ 2132 圈地计划(最小割)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2132 题意:n*m的格子染色黑白,对于格子(i,j)染黑色则价值为A[i][j],白色为B[i][j].若一个格子四周不同颜色的有x个,则额外的价值为x*C[i][j].求最大价值. 思路:将格子黑白染色分成两个集合X和Y.S集合为X中的A和Y中的B,T为X中的B和Y中的A.相邻的连边为两个格子的C值之和.总权值减去最小割即是答案. struct node { int v,cap,ne