bzoj3158 千钧一发
来源:互联网 发布:visual studio mac版 编辑:程序博客网 时间:2024/05/17 23:19
bzoj3158 千钧一发
Description
Input第一行一个正整数N。
第二行共包括N个正整数,第 个正整数表示Ai。
第三行共包括N个正整数,第 个正整数表示Bi。
Output
共一行,包括一个正整数,表示在合法的选择条件下,可以获得的能量值总和的最大值。
Sample Input
4
3 4 5 12
9 8 30 9Sample Output
39
HINT
1<=N<=1000,1<=Ai,Bi<=10^6
这道题也是一道很好的题啊.. 值得去想一想
因为题目要求我们求最大值,那我们就想,能不能把它转化成总和减去损失的最小值呢?对了,就是最小割
首先我们先想一下一个割边的模型,也就是每个点连源连汇,然后割掉其中一条边表示选这个点进入集合所损失的价值,割掉另一条边表示不选这个点进入集合所损失的价值
又由于两个点是会因为某些条件不能在同一个集合中,所以我们要这样建边:
如下:
请注意,中间这一条边是单向边而不是各位认为的双向边
假如两个点都割【选】的边,那么肯定会存在有某个点割【不选】的边使得这种方案的最小割比当前的优,因为存在一条【不选】->【inf】->【不选】的增广路。但是,如果我现在割掉两个【不选】的边,并没有什么关系啊..
那么你也许会问,这个东西保证是二分图吗。那我下面给出证明咯
1.假如两个点都为偶数,那么他们满足第二个条件
2.加入两个点都为奇数,那么他们满足第一个条件
至于为什么,自己好好想想
所以就酱紫咯..
#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <cmath>#define LL long longusing namespace std;const int Maxn = 1100;const int inf = 0x7fffffff;struct node { int x, y, next, c, opp;}a[Maxn*Maxn*5]; int first[Maxn], len;int _min ( int x, int y ){ return x < y ? x : y; }void ins ( int x, int y, int c ){ len ++; int k1 = len; a[len].x = x; a[len].y = y; a[len].c = c; a[len].next = first[x]; first[x] = len; len ++; int k2 = len; a[len].x = y; a[len].y = x; a[len].c = 0; a[len].next = first[y]; first[y] = len; a[k1].opp = k2; a[k2].opp = k1;}int st, ed, h[Maxn];int n;int na[Maxn];int gcd ( int a, int b ){ if ( a == 0 ) return b; return gcd ( b%a, a );}bool check ( int x, int y ){ LL ph = (LL)x*x+(LL)y*y; LL kf = sqrt (ph); if ( kf*kf != ph ) return false; if ( gcd ( x, y ) == 1 ) return true; else return false;}bool bfs (){ queue <int> q; memset ( h, -1, sizeof (h) ); q.push (st); h[st] = 0; while ( !q.empty () ){ int x = q.front (); q.pop (); for ( int k = first[x]; k; k = a[k].next ){ int y = a[k].y; if ( h[y] == -1 && a[k].c > 0 ){ h[y] = h[x]+1; q.push (y); } } } return h[ed] > 0;}int dfs ( int x, int flow ){ if ( x == ed ) return flow; int delta = 0; for ( int k = first[x]; k; k = a[k].next ){ int y = a[k].y; if ( h[y] == h[x]+1 && a[k].c > 0 && flow-delta > 0 ){ int minf = dfs ( y, _min ( a[k].c, flow-delta ) ); delta += minf; a[k].c -= minf; a[a[k].opp].c += minf; } } if ( delta == 0 ) h[x] = -1; return delta;}int main (){ int i, j, k; scanf ( "%d", &n ); for ( i = 1; i <= n; i ++ ) scanf ( "%d", &na[i] ); len = 0; memset ( first, 0, sizeof (first) ); st = 0; ed = n+1; int sum = 0; for ( i = 1; i <= n; i ++ ){ int x; scanf ( "%d", &x ); if ( na[i] % 2 == 1 ) ins ( st, i, x ); else ins ( i, ed, x ); sum += x; } for ( i = 1; i < n; i ++ ){ for ( j = i+1; j <= n; j ++ ){ if ( check ( na[i], na[j] ) == true ){ if ( na[i] % 2 == 0 ) ins ( j, i, inf ); else ins ( i, j, inf ); } } } int ans = 0, delta; while ( bfs () ){ while ( delta = dfs ( st, inf ) ) ans += delta; } printf ( "%d\n", sum-ans ); return 0;}
记住,在进行平方操作时,请注意
论对拍的重要性啊..
0 0
- bzoj3158 千钧一发
- BZOJ3158 千钧一发
- bzoj3158 千钧一发
- BZOJ3158: 千钧一发
- BZOJ3158:千钧一发
- 【BZOJ3158】千钧一发 最小割
- BZOJ3158 千钧一发-最小割
- [BZOJ3158]千钧一发(最小割)
- 【BZOJ3158】千钧一发,网络流之最大权闭合子图
- Gattaca-千钧一发
- 3158: 千钧一发
- bzoj 3158: 千钧一发
- 3158: 千钧一发 最小割
- BZOJ P3158 千钧一发
- BZOJ 3158: 千钧一发
- 3158: 千钧一发/3275: Number
- BZOJ 3158: 千钧一发(最小割)
- BZOJ 3158: 千钧一发 网络流
- 适配器的优化
- java常用工具类之DES和Base64加密解密类
- activity 背景色 透明
- java多线程系列四:synchronized
- POJ 1273 Drainage Ditches -dinic
- bzoj3158 千钧一发
- ACM 搜索 hdu1010 Tempter of the Bone
- 1670 打怪兽
- Web
- Java设计模式之代理设计模式
- 产品经理常用设计方法之一
- 24-网络编程http和简单的JSON
- hdu 2059 龟兔赛跑 DP
- map的遍历方法