博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ2400 Spoj 839 Optimal Marks
阅读量:5052 次
发布时间:2019-06-12

本文共 3744 字,大约阅读时间需要 12 分钟。

首先发现每一位二进制可以分开来做。

然后就变成0、1两种数了,考虑最小割。

设S表示选0,T表示选1,则

对于确定的点向数字对应的S/T连边,边权inf;然后原来图中有边的,互相连边,边权为1。

直接最小割即可,最后还要dfs一下来求出每个未确定的数选的是0还是1。

 

1 /**************************************************************  2     Problem: 2400  3     User: rausen  4     Language: C++  5     Result: Accepted  6     Time:552 ms  7     Memory:3180 kb  8 ****************************************************************/  9   10 #include 
11 #include
12 #include
13 14 using namespace std; 15 typedef long long ll; 16 const int N = 505; 17 const int M = 2005; 18 const int Me = 200005; 19 const int inf = 1e9; 20 21 struct edge { 22 int x, y; 23 edge() {} 24 edge(int _x, int _y) : x(_x), y(_y) {} 25 } E[M]; 26 27 struct edges { 28 int next, to, f; 29 edges() {} 30 edges(int _n, int _t, int _f) : next(_n), to(_t), f(_f) {} 31 } e[Me]; 32 33 int n, m, S, T; 34 int a[N], del[N]; 35 int tot, first[N]; 36 int d[N], q[N]; 37 ll ans; 38 39 inline int read() { 40 int x = 0, sgn = 1; 41 char ch = getchar(); 42 while (ch < '0' || '9' < ch) { 43 if (ch == '-') sgn = -1; 44 ch = getchar(); 45 } 46 while ('0' <= ch && ch <= '9') { 47 x = x * 10 + ch - '0'; 48 ch = getchar(); 49 } 50 return sgn * x; 51 } 52 53 inline void Add_Edges(int x, int y, int f) { 54 e[++tot] = edges(first[x], y, f), first[x] = tot; 55 e[++tot] = edges(first[y], x, 0), first[y] = tot; 56 } 57 58 bool bfs() { 59 int l, r, x, y; 60 memset(d, 0, sizeof(d)); 61 d[q[1] = S] = 1; 62 for (l = r = 1; l != (r + 1) % N; (++l) %= N) 63 for (x = first[q[l]]; x; x = e[x].next) 64 if (!d[y = e[x].to] && e[x].f) 65 d[q[(++r) %= N] = y] = d[q[l]] + 1; 66 return d[T]; 67 } 68 69 int dfs(int p, int lim) { 70 if (p == T || !lim) return lim; 71 int x, y, tmp, rest = lim; 72 for (x = first[p]; x; x = e[x].next) 73 if (d[y = e[x].to] == d[p] + 1 && (tmp = min(e[x].f, rest) > 0)) { 74 rest -= (tmp = dfs(y, tmp)); 75 e[x].f -= tmp, e[x ^ 1].f += tmp; 76 if (!rest) return lim; 77 } 78 if (lim == rest) d[p] = 0; 79 return lim - rest; 80 } 81 82 int Dinic() { 83 int res = 0; 84 while (bfs()) 85 res += dfs(S, inf); 86 return res; 87 } 88 89 void build_graph(int t) { 90 int i; 91 tot = 1, memset(first, 0, sizeof(first)); 92 for (i = 1; i <= n; ++i) 93 if (a[i] >= 0) 94 if (a[i] & t) Add_Edges(i, T, inf); 95 else Add_Edges(S, i ,inf); 96 for (i = 1; i <= m; ++i) 97 Add_Edges(E[i].x, E[i].y, 1), Add_Edges(E[i].y, E[i].x, 1); 98 } 99 100 void find(int p) {101 int x, y;102 d[p] = 1;103 for (x = first[p]; x; x = e[x].next)104 if (e[x ^ 1].f && !d[y = e[x].to]) find(y);105 }106 107 void calc_val(int t) {108 int i;109 memset(d, 0, sizeof(d));110 find(T);111 for (i = 1; i <= n; ++i)112 if (d[i]) del[i] += t;113 }114 115 ll calc_ans() {116 ll res = 0;117 int i;118 for (i = 1; i <= n; ++i)119 res += a[i] >= 0 ? a[i] : del[i];120 return res;121 }122 123 int main() {124 int i;125 n = read(), m = read();126 S = n + 1, T = n + 2;127 for (i = 1; i <= n; ++i)128 a[i] = read();129 for (i = 1; i <= m; ++i)130 E[i] = edge(read(), read());131 for (i = 0; i <= 30; ++i) {132 build_graph(1 << i);133 ans += (ll) (1 << i) * Dinic();134 calc_val(1 << i);135 }136 printf("%lld\n%lld\n", ans, calc_ans());137 return 0;138 }
View Code

 

转载于:https://www.cnblogs.com/rausen/p/4196699.html

你可能感兴趣的文章
InotifyPropertyChanged接口实现简单数据绑定
查看>>
text-align:center 在FireFox及Google浏览器下无效的问题
查看>>
POJ 3687 Labeling Balls(拓扑排序)
查看>>
BZOJ1692: [Usaco2007 Dec]队列变换
查看>>
《POINTERS ON C》(基于ANSI C)知识点及附带问题(三)
查看>>
leetcode dp
查看>>
听力理解-u1-l2
查看>>
微信小程序swiper禁止用户手动滑动
查看>>
简单回射程序小结
查看>>
揭秘Facebook首个数据中心:全球15亿用户的账户信息都在这里
查看>>
7月11
查看>>
IOPS 使用FIO工具测试
查看>>
CSS中behavior属性语法简介
查看>>
2018CHD-ACM新生赛(正式赛)D.刀塔大师lwq I
查看>>
UVA 1451 Average
查看>>
bzoj 4653: [Noi2016]区间
查看>>
经典算法题每日演练——第四题 最长公共子序列
查看>>
Python 通过配置文件 读取参数,执行测试用例,生成测试报告并发送邮件
查看>>
后端开源软件集合
查看>>
How to create dmp file
查看>>