博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JOJ 2453 Candy
阅读量:5742 次
发布时间:2019-06-18

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

JOJ_2453

    假如最后剩下的是价值为1的若干颗糖,显然这些糖分给谁都是无所谓的,因此我们不妨先考虑如何分配最终价值为2的这些糖,这样剩下的只能是价值为1的糖再按需分配,即谁还少就给谁就行了。而且我们在分配价值为2的糖的时候,第i个人得到的总价值不应大于B[i],因为这样相当于浪费了糖,即便B[i]为奇数也是一样的。但是如果将糖的价值视作2,这样是没办法做网络流的,因为容量为2的边有可能只流满了一半,于是不妨将价值为2的糖看作价值为1,将B[i]看作B[i]/2,然后将源点连各个人,容量为B[i]/2,再将人连上相对于自己而言价值为2的糖,容量为INF,最后将各个糖和汇点相连,容量为1。这样做完最大流就可以得到最多分配了多少价值为2的糖,再根据剩下了多少价值为1的糖就可以判断最后能否满足每一个人了。

    但是这样有个致命的问题就是糖太多了,必然会超时,因此我们要想办法减小糖的规模。由于人数很少,这样就可以根据每颗糖被喜欢的情况将糖划分成不超过1024类,这样图的总点数就比较少了。

#include
#include
#define MAXN 1500#define MAXM 15#define MAXE 33000#define INF 0x3f3f3f3fint N, M, S, T, h[1030];int first[MAXN], e, next[MAXE], v[MAXE], flow[MAXE];int d[MAXN], work[MAXN], q[MAXN];long long SUM;void add(int x, int y, int z){ v[e] = y, flow[e] = z; next[e] = first[x], first[x] = e ++; }void init(){ int i, j, k, a, b, cnt; scanf("%d%d", &N, &M); memset(first, -1, sizeof(first)); memset(h, 0, sizeof(h)); e = cnt = 0; for(i = 1; i <= N; i ++) { a = 0; for(j = 1; j <= M; j ++) { scanf("%d", &k); a = a << 1 | (k == 2); } if(!h[a]) ++ cnt; ++ h[a]; } S = 0, T = cnt + M + 1; cnt = 0; for(i = 1; i < 1024; i ++) if(h[i]) { ++ cnt; for(j = 1; j <= M; j ++) if(i & 1 << (M - j)) add(j, cnt + M, INF), add(cnt + M, j, 0); add(cnt + M, T, h[i]), add(T, cnt + M, 0); } SUM = 0; for(i = 1; i <= M; i ++) { scanf("%d", &b), SUM += b; if(b > 1) add(S, i, b >> 1), add(i, S, 0); }}int bfs(){ int i, j, rear = 0; memset(d, -1, sizeof(d[0]) * (T + 1)); d[S] = 0, q[rear ++] = S; for(i = 0; i < rear; i ++) for(j = first[q[i]]; j != -1; j = next[j]) if(flow[j] && d[v[j]] == -1) { d[v[j]] = d[q[i]] + 1, q[rear ++] = v[j]; if(v[j] == T) return 1; } return 0;}int dfs(int cur, int a){ if(cur == T) return a; int t; for(int &i = work[cur]; i != -1; i = next[i]) if(flow[i] && d[v[i]] == d[cur] + 1) if(t = dfs(v[i], a < flow[i] ? a : flow[i])) { flow[i] -= t, flow[i ^ 1] += t; return t; } return 0; }int dinic(){ int ans = 0, t; while(bfs()) { memcpy(work, first, sizeof(first[0]) * (T + 1)); while(t = dfs(S, INF)) ans += t; } return ans;}void solve(){ if(SUM > N * 2) { printf("No\n"); return ; } if(SUM <= N) { printf("Yes\n"); return ; } printf("%s\n", SUM <= N + dinic() ? "Yes" : "No");}int main(){ int t; scanf("%d", &t); while(t --) { init(); solve(); } return 0; }

转载地址:http://gjizx.baihongyu.com/

你可能感兴趣的文章
LR录制脚本时IE打不开的原因
查看>>
Sublime Text 2.0.2,Build 2221注册码
查看>>
最长递增子序列 动态规划
查看>>
原生CSS设置网站主题色—CSS变量赋值
查看>>
webpack 4.0 中 clean-webpack-plugin 的使用
查看>>
中文词频统计
查看>>
POJ 2236 Wireless Network (并查集)
查看>>
python分类
查看>>
GitBlit (1)-- 在linux 安装 GitBlit 并运行
查看>>
程序是如何执行的(一)a=a+1
查看>>
18 已知下面的字符串是通过RANDOM随机数变量md5sum|cut-c 1-8截取后的结果
查看>>
BZOJ - 3578: GTY的人类基因组计划2
查看>>
爱——无题
查看>>
分布式服务框架原来与实践 读书笔记一
查看>>
【http】post和get请求的区别
查看>>
TFS强制撤销某个工作区的文件签出记录
查看>>
EL表达式无法显示Model中的数据
查看>>
ps6-工具的基础使用
查看>>
灵活运用 SQL SERVER FOR XML PATH
查看>>
linux下使用过的命令总结(未整理完)
查看>>