题意

有nnn个数,其中同时满足下面两个条件的数对不能同时选,求选出一些数让和最大.

  • 若两个数aaa,bbb同时满足以下条件,则aaa,bbb不能同时被选

    • 存在正整数ccc,使a∗a+b∗b=c∗ca*a+b*b=c*ca∗a+b∗b=c∗c
    • gcd(a,b)=1gcd(a,b)=1gcd(a,b)=1

分析

看到这熟悉二元关系,就能够用最小割做了.但是乍一看不是二分图的模型,就不能直接连了.所以有一种做法就是拆点.

但是我们看这两个式子可以推出来这的确是一个二分图,而且是奇偶二分图,证明如下:

  • a,ba,ba,b不可能同为偶数,否则不满足gcd(a,b)=1gcd(a,b)=1gcd(a,b)=1
  • a,ba,ba,b不可能同为奇数,证明为
    • 假设存在a,ba,ba,b为奇数且c2=a2+b2c^2=a^2+b^2c2=a2+b2,那么ccc必为偶数,但是a2+b2≡2 (mod 4)a^2+b^2\equiv 2\ (mod\ 4)a2+b2≡2 (mod 4)而c2≡0 (mod 4)c^2\equiv 0\ (mod\ 4)c2≡0 (mod 4),矛盾

综上,存在矛盾的数对一定是奇偶性不同的数字,所以我们用二分图的方式,矛盾就连一条容量为∞\infty∞的边,然后SSS向奇数连容量为数值的边,偶数向TTT连容量为数值的边,最后用所有数的总和减去最小割就行了

CODE

#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
template<typename T>inline void read(T &num) {
char ch; int flg=1;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flg=-flg;
for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
num*=flg;
}
const int inf = 1e9;
const int MAXN = 3005;
const int MAXM = 20005;
int n, m, fir[MAXN], S, T, cnt;
struct edge { int to, nxt; int c; }e[MAXM];
inline void add(int u, int v, int cc) {
e[cnt] = (edge){ v, fir[u], cc }; fir[u] = cnt++;
e[cnt] = (edge){ u, fir[v], 0 }; fir[v] = cnt++;
}
int dis[MAXN], vis[MAXN], info[MAXN], cur, q[MAXN];
inline bool bfs() {
int head = 0, tail = 0;
vis[S] = ++cur; q[tail++] = S;
while(head < tail) {
int u = q[head++];
for(int i = fir[u]; ~i; i = e[i].nxt)
if(e[i].c && vis[e[i].to] != cur)
vis[e[i].to] = cur, dis[e[i].to] = dis[u] + 1, q[tail++] = e[i].to;
}
if(vis[T] == cur) memcpy(info, fir, (T+1)<<2);
return vis[T] == cur;
}
int dfs(int u, int Max) {
if(u == T || !Max) return Max;
int flow=0, delta;
for(int &i = info[u]; ~i; i = e[i].nxt)
if(e[i].c && dis[e[i].to] == dis[u] + 1 && (delta=dfs(e[i].to, min(e[i].c, Max-flow)))) {
e[i].c -= delta, e[i^1].c += delta, flow += delta;
if(flow == Max) return flow;
}
if(!flow) dis[u] = -1;
return flow;
}
inline int dinic() {
memset(vis, 0, sizeof vis);
int flow=0, x;
while(bfs()) {
while((x=dfs(S, inf))) flow+=x;
}
return flow;
}
int A[MAXN], sum;
int gcd(int x, int y) { return y ? gcd(y, x%y) : x; }
inline bool chk(int a,int b)
{
int s = a*a + b*b, q = int(sqrt(s));
if(q * q != s)return 0;
if(gcd(a, b) != 1)return 0; //先判勾股数再判gcd会快好几倍
return 1;
}
int main () {
read(n); S = 0; T = n+1;
memset(fir, -1, sizeof fir);
for(int i = 1; i <= n; ++i) {
read(A[i]); sum += A[i];
if(A[i]&1) add(S, i, A[i]);
else add(i, T, A[i]);
for(int j = 1; j < i; ++j)
if(chk(A[i], A[j])) {
if(A[i]&1) add(i, j, inf);
else add(j, i, inf);
}
}
printf("%d\n", sum-dinic());
}

BZOJ 3275: Number (二分图最小割)的更多相关文章

  1. bzoj 3275 Number(最小割)

    [题意] 给定n个数,要求选出一些数满足 1.存在c,a*a+b*b=c*c 2.gcd(a,b)=1  使得和最大. [思路] 二分图的最大权独立集(可以这么叫么QAQ 先拆点,对于不满足条件的两个 ...

  2. bzoj 3275: Number (最小割)

    题目的意思是要选一些数,但是这些数如果满足两个条件的话就不能一起被选. type arr=record toward,next,cap:longint; end; const maxn=; maxm= ...

  3. bzoj 3158 千钧一发(最小割)

    3158: 千钧一发 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 767  Solved: 290[Submit][Status][Discuss] ...

  4. BZOJ 3275: Number( 最小割 )

    S->每个奇数,每个偶数->T各连一条边, 容量为这个数字.然后不能同时选的两个数连容量为+oo的边. 总数-最大流即是答案. 因为满足a2+b2=c2的a,b一定是一奇一偶或者两个偶数, ...

  5. 【BZOJ-3275&3158】Number&千钧一发 最小割

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 748  Solved: 316[Submit][Status][Discus ...

  6. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  7. [二分图&最小割]

    OTL@assassain 反转源汇的模型: 给定一个二分图,同时选择集合中的两个点会有一个代价,选择每一个点有一个收益,问最大收益是多少 (即两个点在不同的集合中是有冲突关系的) 解法: 用最小割模 ...

  8. [BZOJ 2127] happiness 【最小割】

    题目链接:BZOJ - 2127 题目分析 首先,每个人要么学文科,要么学理科,所以可以想到是一个最小割模型. 我们就确定一个人如果和 S 相连就是学文,如果和 T 相连就是学理. 那么我们再来确定建 ...

  9. BZOJ.3532.[SDOI2014]LIS(最小割ISAP 退流)

    BZOJ 洛谷 \(LIS\)..经典模型? 令\(f_i\)表示以\(i\)结尾的\(LIS\)长度. 如果\(f_i=1\),连边\((S,i,INF)\):如果\(f_i=\max\limits ...

随机推荐

  1. Servlet技术之——概述、实现、细节、获取资源、ServletConfig、ServletContext

    Servlet概述.实现.细节.获取资源.ServletConfig.ServletContext (一) Setvlet基本概述 (1) 什么是Servlet ? Servlet(Server Ap ...

  2. HTML 5 全局 contenteditable 属性

    contenteditable 可以将标签设置为可输入的input,textarea, 但是在ios上,点击或者点击很久input输入框才出来,兼容ios的方法是加一个   -webkit-user- ...

  3. [转帖]MMU内存管理单元

    MMU内存管理单元 https://www.cnblogs.com/alantu2018/p/9002309.html 之前对这一块一直不理解 最近学习了点 CPU time slice 以及 con ...

  4. CentOS7离线安装Mysql(详细安装过程)

    Mysql安装 下载mysql离线安装包 https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.27-1.el7.x86_64.rpm-bundle ...

  5. [C#] LINQ之SelectMany和GroupJoin

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. .NET Core 使用ModelBinder去掉所有参数的空格

    一.前言 通过各种姿势搜索都没搜到这方面的,唯一找到一个比较符合的,但是只适合简单类型,而且代码还没贴全,心累.. 然后查看官网和源码之后,发现继承并实现 IModelBinder和IModelBin ...

  7. 听课笔记--DP--最大子矩阵和

    最大子矩阵问题 给定一个n*n(0<n<=120)的矩阵, 矩阵内元素有正有负, 请找到此矩阵的内部元素和最大的子矩阵 样例输入: 4 0 -2 -7  0  9  2 -6  2  -4 ...

  8. MYSQL编码转换的问题latin1转utf8

    1.先导出 mysqldump --default-character-set=latin1 --create-options=false --set-charset=false  -u root - ...

  9. 验证 vector = 是深拷贝还是浅拷贝

    #include <vector> using namespace std; int main() { int w=1920; int h = 1080; vector<int> ...

  10. 基于【 Docker】三 || Docker的基本操作

    一.Docker常用命令 1.搜索镜像:docker search 镜像名称 2.下载镜像:docker pull 镜像名称:版本号 3.查看镜像:docker images 4.删除镜像:docke ...