BZOJ 3275: Number( 最小割 )

---------------------------------------------------------------------

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn = 3009;

const int INF = 0x7FFFFFFF;

struct edge {

int to, cap;

edge *next, *rev;

} E[1000000], *pt = E, *head[maxn];

inline void add(int u, int v, int w) {

pt->to = v; pt->cap = w; pt->next = head[u]; head[u] = pt++;

}

inline void addedge(int u, int v, int w) {

add(u, v, w); add(v, u, 0);

head[u]->rev = head[v];

head[v]->rev = head[u];

}

edge *cur[maxn], *p[maxn];

int h[maxn], cnt[maxn], S, T, N;

int maxFlow() {

memset(cnt, 0, sizeof cnt);

memset(h, 0, sizeof h);

cnt[0] = N;

edge* e;

int flow = 0;

for(int x = S, A = INF; h[S] < N; ) {

for(e = cur[x]; e; e = e->next)

if(e->cap && h[e->to] + 1 == h[x]) break;

if(e) {

p[e->to] = cur[x] = e;

A = min(e->cap, A);

x = e->to;

if(x == T) {

for(; x != S; x = p[x]->rev->to) {

p[x]->cap -= A;

p[x]->rev->cap += A;

}

flow += A;

A = INF;

}

} else {

if(!--cnt[h[x]]) break;

h[x] = N;

for(e = head[x]; e; e = e->next) if(e->cap && h[e->to] + 1 < h[x]) {

cur[x] = e;

h[x] = h[e->to] + 1;

}

cnt[h[x]]++;

if(x != S) x = p[x]->rev->to;

}

}

return flow;

}

int num[maxn];

int gcd(int x, int y) {

return y ? gcd(y, x % y) : x;

}

bool check(int x, int y) {

int h = gcd(x, y);

if(h != 1) return false;

ll t = ll(x) * x + ll(y) * y;

t = (ll)sqrt(t);

if(t * t == ll(x) * x + ll(y) * y) return true;

return false;

}

int main() {

int n; scanf("%d", &n);

int tot = 0;

S = 0; T = n + 1; N = T + 1;

for(int i = 1; i <= n; i++) {

scanf("%d", num + i);

tot += num[i];

num[i] & 1 ? addedge(S, i, num[i]) : addedge(i, T, num[i]);

}

for(int i = 1; i <= n; i++) if(num[i] & 1)

for(int j = 1; j <= n; j++) if(!(num[j] & 1))

if(check(num[i], num[j])) addedge(i, j, INF);

printf("%d\n", tot - maxFlow());

return 0;

}

---------------------------------------------------------------------

3275: Number

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 504  Solved: 222
[Submit][Status][Discuss]

Description

有N个正整数,需要从中选出一些数,使这些数的和最大。
若两个数a,b同时满足以下条件,则a,b不能同时被选
1:存在正整数C,使a*a+b*b=c*c
2:gcd(a,b)=1

Input

第一行一个正整数n,表示数的个数。

第二行n个正整数a1,a2,?an。

Output

最大的和。

Sample Input

5
3 4 5 6 7

Sample Output

22

HINT

n<=3000。

Source

网络流

时间: 2024-08-01 01:24:15

BZOJ 3275: Number( 最小割 )的相关文章

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 3275: Number

3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discuss] Description 有N个正整数,需要从中选出一些数,使这些数的和最大. 若两个数a,b同时满足以下条件,则a,b不能同时被选 1:存在正整数C,使a*a+b*b=c*c 2:gcd(a,b)=1 Input 第一行一个正整数n,表示数的个数. 第二行n个正整数a1,a2,?an. Out

BZOJ 2561: 最小生成树(最小割)

U,V能在最小(大)生成树上,当且仅当权值比它小(大)的边无法连通U,V. 两次最小割就OK了. --------------------------------------------------------------------- #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<vector> #include<que

BZOJ 2127: happiness( 最小割 )

最小割.. S连每个人(容量:选择理科的愉悦):每个人连T(容量:选择理科的愉悦) . 对于每一组(x, y, w)x和y同选理增加的愉悦w,新建节点V,V连x(INF),V连y(INF), S连V(w) 对于每一组(x, y, w)x和y同选文增加的愉悦w,新建节点V,x连V(INF),y连V(INF), V连T(w) ------------------------------------------------------------------- #include<cstdio> #i

BZOJ 2229 ZJOI2011 最小割 最小割+分治 400AC达成&amp;&amp;2000Submission达成

题目大意:给定一个图,多次询问有多少个点对之间的最小割小于等于某个值 最小割分治- - 首先朴素的想法是做O(n^2)遍网络流 但是这样显然是过不去的 根据一些结论,最小割最多有n-1个,这n-1个最小割构成一个最小割树 别问我为什么- - 因此我们分治寻找这n-1个最小割 每层分治,先任选两个点作为源汇做一遍最小割 然后找出S集和T集,对所有S集的点和T集的点构成的点对用本次得到的最小割更新一遍 注意更新的是全部S集和全部T集,不只是本次分治内部的S集和T集 然后将本次分治的点分成S集和T集,

bzoj3275: Number(最小割)

3275: Number 题目:传送门 题解: 双倍经验@bzoj3158 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #define qread(x) x=read() 7 using namespace std; 8 const int inf=999999999; 9 int

[BZOJ 1797][AHOI2009]最小割(最小割关键边的判断)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1797 分析: 在残余网络中看: 对于第1问: 1.首先这个边必须是满流 2.其次这个边连接的两个点U,V必须属于两个SCC,即这个边必须为一个割 对于第2问: 在第1问的基础上,还要判断U和S.V和T是否分别在同一个SCC中,如果成立,那么这样才是必须的.

BZOJ 2521 最小生成树(最小割)

http://www.lydsy.com/JudgeOnline/problem.php?id=2521 题意:每次能增加一条边的权值1,求最小代价让一条边保证在最小生成树里 思路:如果两个点中有环,那么这条边必须不能是环的最大边,这样子把之前所有的边权值变成V+1-v[i],无向图网络流就可以了 1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5

bzoj 3144 切糕 —— 最小割

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3144 每个点拆成 R 个,连成一条链,边上是权值,割掉代表选这一层: 然后每个点的第 t 层向四周的点的第 t-d 层连边,就能达到选了第 i 条边,则四周的点必须选 i-d ~ T 范围的边,而对方反过来一连,就限制在 i-d ~ i+d 了: 竟然因为忘记 ct=1 而调了一小时呵呵... 代码如下: #include<cstdio> #include<cstring>