题意:一个人要给女孩子们拍照,一共 n 天,m 个女孩子,每天他至多拍 d[i] 张照片,每个女孩子总共要被至少拍 g[i] 次。在第 i 天,可以拍 c[i] 个女孩子,c[i] 个女孩子中每个女孩子在当天被拍的次数是 [li,ri],求最多可以拍多少张照片,以及每天每个可以拍的女孩子被拍了多少张照片。

析:一个很明显网络流,很容易建图,建立一个源点 s 和汇点 t,然后 s 向每一天连一条边,容量上界上 d[i],每个女孩子向汇点连一边,下界是 g[i], 上界是无穷大,然后对于每一天拍的从每一天那个结点向那个女孩子连一条容量上界是 ri,下界是 li,的边,然后就建好图了,就是求最大流,但是这个不是普通的网络流,我们要把它进行转换,首先先根据无源无汇的,建立,因为是有源汇的,所以连一条边 t -> s,INF,然后求一次 超级源点汇点(注意不是 s t) S T 最大流,如果满流就是有可行流,然后再求 s->t 的最大流,结果就是答案。然后再输出解,输出解的时候就是流再加上下界。

代码如下:

  1. #pragma comment(linker, "/STACK:1024000000,1024000000")
  2. #include <cstdio>
  3. #include <string>
  4. #include <cstdlib>
  5. #include <cmath>
  6. #include <iostream>
  7. #include <cstring>
  8. #include <set>
  9. #include <queue>
  10. #include <algorithm>
  11. #include <vector>
  12. #include <map>
  13. #include <cctype>
  14. #include <cmath>
  15. #include <stack>
  16. #include <sstream>
  17. #include <list>
  18. #include <assert.h>
  19. #include <bitset>
  20. #include <numeric>
  21. #define debug() puts("++++")
  22. #define gcd(a, b) __gcd(a, b)
  23. #define lson l,m,rt<<1
  24. #define rson m+1,r,rt<<1|1
  25. #define fi first
  26. #define se second
  27. #define pb push_back
  28. #define sqr(x) ((x)*(x))
  29. #define ms(a,b) memset(a, b, sizeof a)
  30. #define sz size()
  31. #define be begin()
  32. #define ed end()
  33. #define pu push_up
  34. #define pd push_down
  35. #define cl clear()
  36. #define lowbit(x) -x&x
  37. //#define all 1,n,1
  38. #define FOR(i,n,x) for(int i = (x); i < (n); ++i)
  39. #define freopenr freopen("in.in", "r", stdin)
  40. #define freopenw freopen("out.out", "w", stdout)
  41. using namespace std;
  42.  
  43. typedef long long LL;
  44. typedef unsigned long long ULL;
  45. typedef pair<int, int> P;
  46. const int INF = 0x3f3f3f3f;
  47. const LL LNF = 1e17;
  48. const double inf = 1e20;
  49. const double PI = acos(-1.0);
  50. const double eps = 1e-8;
  51. const int maxn = 1500 + 50;
  52. const int maxm = 1e6 + 10;
  53. const LL mod = 1000000007;
  54. const int dr[] = {-1, 1, 0, 0, 1, 1, -1, -1};
  55. const int dc[] = {0, 0, 1, -1, 1, -1, 1, -1};
  56. const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
  57. int n, m;
  58. const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  59. const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  60. inline bool is_in(int r, int c) {
  61. return r >= 0 && r < n && c >= 0 && c < m;
  62. }
  63. inline int readInt(){ int x; scanf("%d", &x); return x; }
  64.  
  65. struct Edge{
  66. int from, to, cap, flow;
  67. };
  68.  
  69. struct Dinic{
  70. int n, m, s, t;
  71. vector<Edge> edges;
  72. vector<int> G[maxn];
  73. bool vis[maxn];
  74. int d[maxn];
  75. int cur[maxn];
  76.  
  77. void init(int n){
  78. FOR(i, n, 0) G[i].cl;
  79. edges.cl;
  80. }
  81.  
  82. void addEdge(int from, int to, int cap){
  83. edges.pb((Edge){from, to, cap, 0});
  84. edges.pb((Edge){to, from, 0, 0});
  85. m = edges.sz;
  86. G[from].pb(m - 2);
  87. G[to].pb(m - 1);
  88. }
  89.  
  90. bool bfs(){
  91. ms(vis, 0); d[s] = 0; vis[s] = 1;
  92. queue<int> q; q.push(s);
  93.  
  94. while(!q.empty()){
  95. int u = q.front(); q.pop();
  96. for(int i = 0; i < G[u].sz; ++i){
  97. Edge &e = edges[G[u][i]];
  98. if(!vis[e.to] && e.cap > e.flow){
  99. vis[e.to] = 1;
  100. d[e.to] = d[u] + 1;
  101. q.push(e.to);
  102. }
  103. }
  104. }
  105. return vis[t];
  106. }
  107.  
  108. int dfs(int u, int a){
  109. if(u == t || a == 0) return a;
  110. int flow = 0, f;
  111. for(int &i = cur[u]; i < G[u].sz; ++i){
  112. Edge &e = edges[G[u][i]];
  113. if(d[e.to] == d[u] + 1 && (f = dfs(e.to, min(a, e.cap-e.flow))) > 0){
  114. e.flow += f;
  115. edges[G[u][i]^1].flow -= f;
  116. flow += f;
  117. a -= f;
  118. if(a == 0) break;
  119. }
  120. }
  121. return flow;
  122. }
  123.  
  124. int maxFlow(int s, int t){
  125. this->s = s; this->t = t;
  126. int flow = 0;
  127. while(bfs()){ ms(cur, 0); flow += dfs(s, INF); }
  128. return flow;
  129. }
  130. };
  131. Dinic dinic;
  132.  
  133. int down[100000], in[100000], d[maxn], g[maxn];
  134.  
  135. int main(){
  136. while(scanf("%d %d", &n, &m) == 2){
  137. int s = 0, t = n + m + 1;
  138. dinic.init(t + 10);
  139. ms(in, 0);
  140. for(int i = 1; i <= m; ++i)
  141. scanf("%d", g + i);
  142.  
  143. int cnt = 0;
  144. for(int i = 1; i <= n; ++i){
  145. int c; scanf("%d %d", &c, d + i);
  146. int x, l, r;
  147. while(c--){
  148. scanf("%d %d %d", &x, &l, &r);
  149. down[cnt++] = l;
  150. dinic.addEdge(i, x + n + 1, r - l);
  151. in[i] -= l;
  152. in[x+n+1] += l;
  153. }
  154. }
  155. for(int i = 1; i <= n; ++i)
  156. dinic.addEdge(s, i, d[i]);
  157. for(int i = 1; i <= m; ++i){
  158. dinic.addEdge(i + n, t, INF - g[i]);
  159. in[i+n] -= g[i];
  160. in[t] += g[i];
  161. }
  162. int S = t + 1, T = t + 2;
  163. int ans = 0;
  164. for(int i = 0; i <= t; ++i)
  165. if(in[i] > 0) dinic.addEdge(S, i, in[i]), ans += in[i];
  166. else if(in[i] < 0) dinic.addEdge(i, T, -in[i]);
  167. dinic.addEdge(t, s, INF);
  168. if(ans != dinic.maxFlow(S, T)){ printf("-1\n\n"); continue; }
  169. printf("%d\n", dinic.maxFlow(s, t));
  170. for(int i = 0; i < cnt; ++i) printf("%d\n", dinic.edges[i<<1].flow + down[i]);
  171. printf("\n");
  172. }
  173. return 0;
  174. }

  

ZOJ 3229 Shoot the Bullet (有源有汇有上下界最大流)的更多相关文章

  1. SGU 176 Flow construction (有源有汇有上下界最小流)

    题意:给定 n 个点,m 条有向边,如果有向边的标号是1的话,就表示该边的上界下界都为容量 ,如果有向边的标号为0的哈,表示该边的下界为0,上界为容量 ,现在问,从 1 到 n 的最小流是多少,并输出 ...

  2. ZOJ 2314 (sgu 194) Reactor Cooling (无源汇有上下界最大流)

    题意: 给定n个点和m条边, 每条边有流量上下限[b,c], 求是否存在一种流动方法使得每条边流量在范围内, 而且每个点的流入 = 流出 分析: 无源汇有上下界最大流模板, 记录每个点流的 in 和 ...

  3. ZOJ 3229 Shoot the Bullet(有源汇上下界最大流)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3442 题目大意: 一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝给 ...

  4. ZOJ - 3229 Shoot the Bullet (有源汇点上下界最大流)

    题意:要在n天里给m个女生拍照,每个女生有拍照数量的下限Gi,每天有拍照数量的上限Di,每天当中每个人有拍照的上限Lij和Rij.求在满足限制的基础上,所有人最大能拍多少张照片. 分析:抛开限制,显然 ...

  5. POJ 2396 有源有汇有上下界可行流问题

    题意:给一个矩阵,给出每行每列之和,附加一些条件,如第i行第j列数必需大于(小于)多少. 思路题解:矩阵模型,模拟网络流,行.列标号为结点,构图,附加s,t,s连行标(容量上下限每行之和(必需以这个 ...

  6. ZOJ 3229 Shoot the Bullet | 有源汇可行流

    题目: 射命丸文要给幻想乡的居民照相,共照n天m个人,每天射命丸文照相数不多于d个,且一个人n天一共被拍的照片不能少于g个,且每天可照的人有限制,且这些人今天照的相片必须在[l,r]以内,求是否有可行 ...

  7. ZOJ 3229 Shoot the Bullet(有源汇的上下界最大流)

    Description Gensokyo is a world which exists quietly beside ours, separated by a mystical border. It ...

  8. ZOJ 3229 Shoot the Bullet [上下界最大流]

    ZOJ 3229 Shoot the Bullet 题意:此生无悔入东方 上下界最大流 spj挂掉了我也不知道对不对,把代码放这里吧以后正常了可能会评测一下 #include <iostream ...

  9. Shoot the Bullet(有源汇带上下界最大流)

    有源汇带上下界最大流 在原图基础上连一条汇点到源点流量为inf的边,将有源汇网络流转化为无源汇网络流用相同方法判断是否满流,如果满流再跑一边源点到汇点的最大流就是答案 例题:Shoot the Bul ...

随机推荐

  1. HTML/CSS基础知识(二)

    Q:HTML5是什么?为什么要用HTML5?有什么新特性?移除了哪些元素? HTML5是HTML的最新版本,2014年10月由万维网联盟(W3C)完成标准制定.目标是替换1999年制定的HTML4.0 ...

  2. vim常用操作和使用技巧

    vi是linux与unix下的常用文本编辑器,其运行稳定,使用方便,本文将分两部分对其常用操作技巧和配置进行阐述,其中参考了网上的一些文章,对作者表示感谢 PART1 操作技巧 说明: 以下的例子中  ...

  3. Nginx 安装配置教程

    1.安装 Nginx 的先决条件 依赖库:GCC, PCRE, zlib, OpenSSL . * GCC (Nginx 由 C 语言编写,因此需要在系统上安装一个编译工具) 基本上 Linux 自带 ...

  4. LeetCode contest-95[876,877,👁878]

    876. Middle of the Linked List first submission # Definition for singly-linked list. # class ListNod ...

  5. [UnityShader基础]03.透明度混合

    如果要渲染半透明物体,那么就需要用到透明度混合. 需要注意的有这几点: 1.设置标签:Tags { "Queue"="Transparent" "Ig ...

  6. jQuery入门基础(动画效果)

    一.隐藏显示 1.show()--显示隐藏的被选择元素 例:$(selector).show(speed,callback); 2.hide()--隐藏被选元素的内容 例:$(selector).hi ...

  7. jquery.cookie用法及其注意点

    jquery.cookie是一个轻量级的cookie插件,由于已被封装好,可拿来即用. 基本的创建.读取.删除见另一篇文章 浅谈localStorage.sessionStorage 与cookie  ...

  8. Adreno GPU Profiler

    Adreno GPU Profiler,除了UNITY profiler外的一个备选,似乎不能看CPU,内存?

  9. 1011 A+B 和 C (15 分)

    pragma warning(disable:4996) a-c+b>0? 考虑可能越界 在循环体内判断,然后有序号输出 输入输出格式看多个题然后总结下 不会处理单行数据 include < ...

  10. CentOS6.5搭建OpenVas完全搭建手册(搭建过程总结及小记)

    一.OpenVAS 介绍 1.关于OpenVAS OpenVAS(Open Vulnerability Assessment System)是一套开源的漏洞扫描系统,早期Nessus 是其中一个最流行 ...