Shoot the Bullet(有源汇带上下界最大流)
有源汇带上下界最大流
在原图基础上连一条汇点到源点流量为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(有源汇带上下界最大流)的更多相关文章
- ZOJ3229 Shoot the Bullet(有源汇的上下界最大流)
#pragma warning(disable:4996) #include <iostream> #include <cstring> #include <string ...
- zoj3229 Shoot the Bullet(有源汇有上下界的最大流)
题意: 一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝给给定的C个女神拍照,每天拍照数不能超过D张,而且给每个女神i拍照有数量限制[Li,Ri],对于每个女神n天的拍照总和不能少于Gi,如果有解求屌 ...
- LOJ116 - 有源汇有上下界最大流
原题链接 Description 模板题啦~ Code //有源汇有上下界最大流 #include <cstdio> #include <cstring> #include & ...
- 【Loj116】有源汇有上下界最大流(网络流)
[Loj116]有源汇有上下界最大流(网络流) 题面 Loj 题解 模板题. #include<iostream> #include<cstdio> #include<c ...
- loj #116. 有源汇有上下界最大流
题目链接 有源汇有上下界最大流,->上下界网络流 注意细节,重置cur和dis数组时,有n+2个点 #include<cstdio> #include<algorithm> ...
- loj #117. 有源汇有上下界最小流
题目链接 有源汇有上下界最小流,->上下界网络流 注意细节,边数组也要算上后加到SS,TT边. #include<cstdio> #include<algorithm> ...
- LOJ.117.[模板]有源汇有上下界最小流(Dinic)
题目链接 有源汇有上下界最小流 Sol1. 首先和无源汇网络流一样建图,求SS->TT最大流: 然后连边(T->S,[0,INF]),再求一遍SS->TT最大流,答案为新添加边的流量 ...
- [poj] 2396 [zoj] 1994 budget || 有源汇的上下界可行流
poj原题 zoj原题 //注意zoj最后一行不要多输出空行 现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出.列代表不同赛区支出的矩阵.组委会曾经开会讨论过各类支出的总和,以及各赛区 ...
- 【LOJ116】有源汇有上下界最大流(模板题)
点此看题面 大致题意: 给你每条边的流量上下界,让你先判断是否存在可行流.若存在,则输出最大流. 无源汇上下界可行流 在做此题之前,最好先去看看这道题目:[LOJ115]无源汇有上下界可行流. 大致思 ...
随机推荐
- iptables 基础
SNAT 和 DNAT 是 iptables 中使用 NAT 规则相关的的两个重要概念.如上图所示,如果内网主机访问外网而经过路由时,源 IP 会发生改变,这种变更行为就是 SNAT:反之,当外网的数 ...
- kubernetes实战(三十):CentOS 8 二进制 高可用 安装 k8s 1.17.x
1. 基本说明 本文章将演示CentOS 8二进制方式安装高可用k8s 1.17.x,相对于其他版本,二进制安装方式并无太大区别. 2. 基本环境配置 主机信息 192.168.1.19 k8s-ma ...
- javeweb_学生信息添加系统
在text.jsp中画出界面,以及设置提交选项的限制 <%@ page language="java" contentType="text/html; charse ...
- JWT实现分布式Session
JWT是什么 JWT一看就是简称,它的全称JSON Web Token,从字面上我们看出 1.数据是JSON格式 2.用于Web应用 3.是一个Token,也就是一个令牌方式 看看官方的说明,它定义了 ...
- cocos2dx Geometry Size和Rect
Size 代码都是基础代码不注释了,写一些特别的 1.赋值时可以接收Size和Vec2类型的值,保证的类型的兼容性 2.对运算符进行了重载,可以按照正常的数学逻辑运算 3..可以使用equals对比大 ...
- 从零开始のcocos2dx生活(五)ActionEase
文章目录 sineEaseIn sineEaseOut sineEaseInOut expoEaseIn expoEaseOut expoEaseInOut easeIn easeOut easeIn ...
- Java锁对象和条件对象的使用
锁对象 临界区:临界区是一个特殊的代码段,该代码段访问某种特殊的公共资源,该资源同一时间只允许一个线程使用. Java中可以使用锁对象创造一个临界区: myLock.lock(); try { 关键代 ...
- Activity启动过程源码分析(Android 8.0)
Activity启动过程源码分析 本文来Activity的启动流程,一般我们都是通过startActivity或startActivityForResult来启动目标activity,那么我们就由此出 ...
- C# 图片转二进制
/// <summary> /// 将目标路径转为image /// </summary> /// <param name="path">图片路 ...
- 【php学习】图片处理三步走
前两天要对一张图片进行处理,其实很简单,就是在图片上加上字符串,一个图片而已,但是自己如同得了短暂性失忆似的,图片操作的函数一个都想不起来.所以就抽空整理了一下图片操作函数. 1. 创建画布 从文件中 ...