有源汇带上下界最大流

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

例题:Shoot the Bullet 东方文花帖

题目传送门

#include <bits/stdc++.h>
using namespace std;
/* freopen("k.in", "r", stdin);
freopen("k.out", "w", stdout); */
// clock_t c1 = clock();
// std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define ls ((x) << 1)
#define rs ((x) << 1 | 1)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef vector<int, int> VII;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 2e3 + 7;
const ll MAXM = 1e5 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-6;
const double pi = acos(-1.0);
int cnt = -1, head[MAXM], dis[MAXN], cur[MAXM];
int n, m;
struct Edge
{
int to, v, net;
Edge(int _to = 0, int _v = 0, int _net = 0) { to = _to, v = _v, net = _net; }
} e[MAXM << 1]; ///共有n*2条边
void add_edge(int from, int to, int v)
{ ///链式前向星
e[++cnt] = Edge(to, v, head[from]);
head[from] = cnt;
e[++cnt] = Edge(from, 0, head[to]);
head[to] = cnt;
}
int bfs(int st, int ed)
{ ///建立层次图
queue<int> que;
memset(dis, -1, sizeof(dis));
dis[st] = 0;
que.push(st);
while (!que.empty())
{
int x = que.front();
que.pop();
for (int i = head[x]; ~i; i = e[i].net)
{
int now = e[i].to;
if (dis[now] == -1 && e[i].v)
{
que.push(now);
dis[now] = dis[x] + 1;
}
}
}
return dis[ed] != -1;
}
int dfs(int x, int t, int maxflow)
{
if (x == t)
return maxflow;
int ans = 0;
for (int i = cur[x]; ~i; i = e[i].net)
{ ///当前弧优化
int now = e[i].to;
if (dis[now] != dis[x] + 1 || e[i].v == 0 || ans >= maxflow)
continue;
cur[x] = i;
int f = dfs(now, t, min(e[i].v, maxflow - ans));
e[i].v -= f;
e[i ^ 1].v += f; ///反向边加流量
ans += f;
}
if (!ans)
dis[x] = -1; ///炸点优化
return ans;
}
int Dinic(int st, int ed)
{
int ans = 0;
while (bfs(st, ed))
{
memcpy(cur, head, sizeof(head));
int k;
while ((k = dfs(st, ed, inf)))
ans += k;
}
return ans;
}
int totflow[MAXN];
int ans[MAXM];
int lowf[MAXN];
void init()
{
cnt = -1;
memset(head, -1, sizeof(head));
memset(totflow, 0, sizeof(totflow));
memset(lowf, 0, sizeof(lowf));
}
int day[MAXN], girl[MAXN];
int main()
{
while (~scanf("%d%d", &n, &m))
{
init();
int st = 0, ed = n + m + 1;
for (int i = 1; i <= m; i++)
{
scanf("%d", &girl[i]);
totflow[n + i] -= girl[i];
totflow[ed] += girl[i];
}
int tot = 0;
for (int i = 1; i <= n; i++)
{
int c, d;
scanf("%d%d", &c, &day[i]);
for (int j = 1; j <= c; j++)
{
int t, l, r;
scanf("%d%d%d", &t, &l, &r);
++t;
lowf[++tot] = l;
totflow[i] -= l;
totflow[n + t] += l;
add_edge(i, n + t, r - l);
}
}
for (int i = 1; i <= m; i++)
add_edge(n + i, ed, inf);
for (int i = 1; i <= n; i++)
add_edge(st, i, day[i]);
add_edge(ed, st, inf);
int ss = n + m + 2, tt = n + m + 3;
int sumflow = 0; for (int i = 0; i <= n + m + 1; i++)
{
if (totflow[i] < 0)
add_edge(i, tt, -totflow[i]);
else if (totflow[i] > 0)
{
sumflow += totflow[i];
add_edge(ss, i, totflow[i]);
}
} if (Dinic(ss, tt) == sumflow)
{
printf("%d\n", Dinic(st, ed));
for (int i = 1; i <= tot; i++)
printf("%d\n", e[((i - 1) << 1) | 1].v + lowf[i]);
}
else
printf("-1\n");
printf("\n");
}
return 0;
}

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

  1. ZOJ3229 Shoot the Bullet(有源汇的上下界最大流)

    #pragma warning(disable:4996) #include <iostream> #include <cstring> #include <string ...

  2. zoj3229 Shoot the Bullet(有源汇有上下界的最大流)

    题意: 一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝给给定的C个女神拍照,每天拍照数不能超过D张,而且给每个女神i拍照有数量限制[Li,Ri],对于每个女神n天的拍照总和不能少于Gi,如果有解求屌 ...

  3. LOJ116 - 有源汇有上下界最大流

    原题链接 Description 模板题啦~ Code //有源汇有上下界最大流 #include <cstdio> #include <cstring> #include & ...

  4. 【Loj116】有源汇有上下界最大流(网络流)

    [Loj116]有源汇有上下界最大流(网络流) 题面 Loj 题解 模板题. #include<iostream> #include<cstdio> #include<c ...

  5. loj #116. 有源汇有上下界最大流

    题目链接 有源汇有上下界最大流,->上下界网络流 注意细节,重置cur和dis数组时,有n+2个点 #include<cstdio> #include<algorithm> ...

  6. loj #117. 有源汇有上下界最小流

    题目链接 有源汇有上下界最小流,->上下界网络流 注意细节,边数组也要算上后加到SS,TT边. #include<cstdio> #include<algorithm> ...

  7. LOJ.117.[模板]有源汇有上下界最小流(Dinic)

    题目链接 有源汇有上下界最小流 Sol1. 首先和无源汇网络流一样建图,求SS->TT最大流: 然后连边(T->S,[0,INF]),再求一遍SS->TT最大流,答案为新添加边的流量 ...

  8. [poj] 2396 [zoj] 1994 budget || 有源汇的上下界可行流

    poj原题 zoj原题 //注意zoj最后一行不要多输出空行 现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出.列代表不同赛区支出的矩阵.组委会曾经开会讨论过各类支出的总和,以及各赛区 ...

  9. 【LOJ116】有源汇有上下界最大流(模板题)

    点此看题面 大致题意: 给你每条边的流量上下界,让你先判断是否存在可行流.若存在,则输出最大流. 无源汇上下界可行流 在做此题之前,最好先去看看这道题目:[LOJ115]无源汇有上下界可行流. 大致思 ...

随机推荐

  1. 写时拷贝COW(copy-on-write)

        写时拷贝技术是通过"引用计数"实现的,在分配空间的时候多分配4个字节,用来记录有多少个指针指向块空间,当有新的指针指向这块空间时,引用计数加一,当要释放这块空间时,引用计数 ...

  2. asdf

    [root@host01 ~]# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' TIME_WAIT 3 CL ...

  3. Android CTS中neverallow规则生成过程

    CTS里面SELinux相关测试中neverallow测试项占绝大多数,Android系统开发者都应该知道,在修改sepolicy时,需要确保不能违反这些neverallow规则,不然会过不了CTS. ...

  4. 前端——BOM与DOM

    目录 前戏 window对象 window的子对象 navigator对象(了解即可) screen对象(了解即可) history对象(了解即可) location对象 弹出框 计时相关 DOM H ...

  5. Centos 7.5安装 Nginx 1.14.1

    1. 准备工作 查看系统版本 输入命令 cat /etc/redhat-release 我的Centos版本 CentOS Linux release 7.5.1804 (Core) 安装nginx所 ...

  6. 深入CAS的底层实现机制,以及对应的使用风险

    概述 CAS(Compare-and-Swap),即比较并替换,是一种实现并发算法时常用到的技术,Java并发包中的很多类都使用了CAS技术.CAS也是现在面试经常问的问题,本文将深入的介绍CAS的原 ...

  7. MyBatis使用mapper动态代理实现DAO接口

    工具: mysql 5.5.62   IDEA 参考自:https://www.cnblogs.com/best/p/5688040.html 遇到的问题: 无法读取src/main/java下配置文 ...

  8. 洛谷$1220$ 关路灯 记搜/$DP$

    \(Sol\) 约定\(pos\)为老张所处的位置的路灯号,\(i<pos,j>pos\). 显然,如果\(i\)和\(j\)都关了,那么它们之间的所有灯一定也都关了. 设\(f[i][j ...

  9. 机器学习之路--Matplotlib

    1.绘制折线图 在pandas里面有一种数据类型为datatime ,可以将不规范的日期改为:xxxx-xx-xx import pandas as pd import numpy as np a = ...

  10. spring-boot第一章:快速开始

    快速开始 创建pom.xml文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns= ...