bzoj3275 Number
Number
Time Limit: 10 Sec Memory Limit: 128 MB
Description
有\(N\)个正整数,需要从中选出一些数,使这些数的和最大。
若两个数\(a,b\)同时满足以下条件,则\(a,b\)不能同时被选
1:存在正整数\(C\),使\(a*a+b*b=c*c\)
2:\(gcd(a,b)=1\)
Input
第一行一个正整数\(n\),表示数的个数。\(n<=3000\)
第二行\(n\)个正整数\(a_1,a_2,...a_n\)
Output
最大的和
Sample Input
5
3 4 5 6 7
Sample Output
22
今天下午本来仔细的再学一下数学和其他相关知识的。。。。发现很多题都或多或少有点问题。。。。尴尬癌犯了啊~~~
写一道网络流的题吧。
表示我记得千钧一发。。。。一模一样有木有。。。
复习一下网络流吧(就算省选考到我也不一定会建图啊233)
#include<bits/stdc++.h>
using namespace std;
const int s = 0, t = 3010, maxn = 4001, INF = 0x3f3f3f3f;
struct lpl{
int to, dis;
}lin;
int even[maxn], odd[maxn], layer[maxn];
int n, x, cnt = -1, tot_1, tot_2;
long long ans;
vector<lpl> edge;
vector<int> point[maxn];
queue<int> q;
inline void putit()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i){
scanf("%d", &x); ans += x;
if(x & 1) odd[++tot_1] = x;
else even[++tot_2] = x;
}
}
inline void connect(int a, int b, int w)
{
cnt++; lin.to = b; lin.dis = w; point[a].push_back(cnt); edge.push_back(lin);
cnt++; lin.to = a; lin.dis = 0; point[b].push_back(cnt); edge.push_back(lin);
}
inline void prepare()
{
for(int i = 1; i <= tot_1; ++i) connect(s, i, odd[i]);
for(int i = 1; i <= tot_2; ++i) connect(i + tot_1, t, even[i]);
}
inline int gcd(int a, int b)
{
if(a < b) swap(a, b);
return (a % b == 0) ? b : gcd(b, a % b);
}
inline bool check(int a, int b)
{
if(gcd(a, b) != 1) return false;
long long c = sqrt((long long)a * a + b * b);
if(c * c == ((long long)a * a + b * b)) return true;
return false;
}
inline void workk()
{
for(int i = 1; i <= tot_1; ++i)
for(int j = 1; j <= tot_2; ++j)
if(check(odd[i], even[j])) connect(i, j + tot_1, INF);
}
inline bool bfs()
{
memset(layer, 0, sizeof(layer));
layer[s] = 1; q.push(s);
while(!q.empty()){
int now = q.front(); q.pop();
for(int i = point[now].size() - 1; i >= 0; --i){
lin = edge[point[now][i]];
if(layer[lin.to] || !lin.dis) continue;
layer[lin.to] = layer[now] + 1; q.push(lin.to);
}
}
return layer[t];
}
long long dfs(int a, int w)
{
if(a == t || w == 0) return w;
long long ret = 0;
for(int i = point[a].size() - 1; i >= 0; --i){
int now = point[a][i];
if(layer[edge[now].to] != layer[a] + 1 || edge[now].dis <= 0) continue;
long long tmp = dfs(edge[now].to, min(edge[now].dis, w));
edge[now].dis -= tmp; edge[now ^ 1].dis += tmp; w -= tmp; ret += tmp;
if(!w) break;
}
return ret;
}
inline long long Dinic()
{
long long ret = 0;
while(bfs()) ret += dfs(s, INF);
return ret;
}
int main()
{
putit();
prepare();
workk();
cout << ans - Dinic();
return 0;
}
心如花木,向阳而生。