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

  网络流

Solution

  所以这道题a的数据范围是什么......用long long可以过,不知道int行不行。

  嗯,把所有有关系的数字连一条边,这道题就变成了选出一些点使这些点两两没有边相连,求最大点权。这样就变成了最大点权独立集问题。

  然后好像这个图一定是二分图,就可以用网络流做了。如果不是二分图就是NP问题了233。

  有一个奇怪的定理:最大点权独立集 = 总权值 - 最小点权覆盖集 = 总权值 - 最小割 = 总权值 - 最大流。

  好像不只一个定理,怪我咯。

  把每个数字拆成两个点,从源点连向一个点,另一个点连向汇点,边权均为数字大小。然后把有关系的点之间连一条边,边权无限大。

  跑一遍最大流,答案就是总权值 - 最大流 / 2。

 #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = ;
struct edge
{
int v, nxt;
ll w;
}e[];
queue<int> Q;
ll d[];
int fst[], etot = , sss, ttt, level[]; void addedge(int u, int v, ll w)
{
e[++etot] = (edge){v, fst[u], w}, fst[u] = etot;
} bool istri(ll a, ll b)
{
ll c = (ll)sqrt(a * a + b * b + 0.1);
return c * c == a * a + b * b;
} ll gcd(ll a, ll b)
{
return b ? gcd(b, a % b) : a;
} int BFS()
{
memset(level, , sizeof(level));
Q.push(sss), level[sss] = ;
while(!Q.empty())
{
int u = Q.front();
Q.pop();
for(int i = fst[u]; i; i = e[i].nxt)
if(!level[e[i].v] && e[i].w)
Q.push(e[i].v), level[e[i].v] = level[u] + ;
}
return level[ttt];
} ll Dinic(int u, ll lim)
{
ll tmp = lim;
if(u == ttt) return lim;
for(int i = fst[u]; i; i = e[i].nxt)
if(level[e[i].v] == level[u] + && e[i].w)
{
ll flow = Dinic(e[i].v, min(tmp, e[i].w));
e[i].w -= flow, e[i ^ ].w += flow;
if(!(tmp -= flow)) break;
}
if(tmp == lim) level[u] = ;
return lim - tmp;
} int main()
{
int n;
ll ans = ;
cin >> n;
sss = (n << ) + , ttt = (n << ) + ;
for(int i = ; i <= n; i++)
cin >> d[i];
for(int i = ; i <= n; i++)
{
addedge(sss, i, d[i]), addedge(i, sss, );
addedge(i + n, ttt, d[i]), addedge(ttt, i + n, );
}
for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++)
if(istri(d[i], d[j]) && gcd(d[i], d[j]) == )
addedge(i, j + n, INF), addedge(j + n, i, );
while(BFS())
ans += Dinic(sss, INF);
ans = -(ans >> );
for(int i = ; i <= n; i++)
ans += d[i];
cout << ans << endl;
return ;
}

[BZOJ3275] Number (网络流)的更多相关文章

  1. [BZOJ3275]Number解题报告|网络流

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

  2. bzoj3275: Number

    最小割...然后推一下可知不能的情况必定为一奇一偶,于是s->奇->偶->t.跑最小割即可. #include<cstdio> #include<cstring&g ...

  3. bzoj3275: Number(最小割)

    3275: Number 题目:传送门 题解: 双倍经验@bzoj3158 代码: #include<cstdio> #include<cstring> #include< ...

  4. 【最小割】【Dinic】bzoj3275 Number

    每个点拆点,分别向源/汇连a[i]的边,满足条件的相互连INF的边,答案为sum-maxflow*2. 因为若有几个点不能同时被选,我们要贪心地选择其中和尽量大的部分,这可以由最小割来保证. #inc ...

  5. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

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

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

  7. 【BZOJ3275】Number 最小割

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

  8. 【POJ2699】The Maximum Number of Strong Kings(网络流)

    Description A tournament can be represented by a complete graph in which each vertex denotes a playe ...

  9. POJ 2699 The Maximum Number of Strong Kings ——网络流

    一定存在一种最优方案,使得分数前几个人是SK 所以我们可以二分答案或者枚举,然后就是经典的网络流建模. 另:输入很Excited #include <cstdio> #include &l ...

随机推荐

  1. Java线程池ThreadPoolExector的源码分析

    前言:线程是我们在学习java过程中非常重要的也是绕不开的一个知识点,它的重要程度可以说是java的核心之一,线程具有不可轻视的作用,对于我们提高程序的运行效率.压榨CPU处理能力.多条线路同时运行等 ...

  2. Egret学习笔记 (Egret打飞机-7.实现敌机工厂)

    在游戏过程之,敌机是源源不断的冲屏幕上方往下飞,如果我们每一架敌机都直接new的话,在飞机很多的情况下,也许有性能问题. 就像前面子弹对象池一样,我们也要实现一个飞机对象池,也就是标题说的敌机工厂(之 ...

  3. nyoj161 取石子 (四) 威佐夫博弈

    思路:详细证明见博弈总结 如何判断威佐夫博弈的奇异局势? 对于状态(a, b),c = b - a,如果是奇异局势必定满足 a == c * (1+√5)/ 2. AC代码 #include < ...

  4. AGC010 - D: Decrementing

    原题链接 题意简述 给出一个个数的序列,足够聪明的AB两人轮流进行以下操作: 令一个大于1的数减1,然后所有数除以. 如果一个人不能操作了,那么他就输了. 输入保证所有数都是正整数并且. 分析 这是一 ...

  5. Storm日志分析调研及其实时架构

    1.Storm第一个Demo 2.Windows下基于eclipse的Storm应用开发与调试 3.Storm实例+mysql数据库保存 4.Storm原理介绍 5. flume+kafka+stor ...

  6. 利用linq的Take Skip方法解决 集合拆分的问题

    public static void Main(string[] args) { List<string> list = new List<string>(); ; i < ...

  7. linux ftp及C/S服务架构

    乱码转换工具使用convmv软件:windows中文字符编码为GB2312 linux中文字符编码为utf-8选项:-f:源文件中中文字符编码-t:转换成字符编码-r:代表递归--notest:不测试 ...

  8. ActiveMQ的运用

    MQ的消息队列模式有2种,一种是点对点模式,一种是订阅模式. 点对点模式:点对点的模式主要建立在一个队列上面,当连接一个列队的时候,发送端不需要知道接收端是否正在接收,可以直接向ActiveMQ发送消 ...

  9. 关于druid的配置说明

    <bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter"> & ...

  10. HI3531网络tftp、nfs加载

     ifconfig eth0 hw ether 00:00:23:34:45:66; ifconfig eth0 192.168.1.10 netmask 255.255.255.0; route a ...