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]无源汇有上下界可行流. 大致思 ...
随机推荐
- 理解C/C++的复杂声明
理解C/C++的复杂声明 曾经碰到过让你迷惑不解.类似于int * (* (*fp1) (int) ) [10];这样的变量声明吗?本文将由易到难,一步一步教会你如何理解这种复C/C ...
- 使用springboot + druid + mybatisplus完成多数据源配置
一. 简介 1. 版本 springboot版本为2.0.3.RELEASE,mybatisplus版本为2.1.9, druid版本为1.1.9,swagger版本为2.7.0 2. 项目地址 ...
- ubuntu conda install ERROR missing write permission错误
报错: ondaIOError: Missing write permissions in: /usr/local/anaconda3 # # You don't appear to have the ...
- 【题解】NOIP2016 提高组 简要题解
[题解]NOIP2016 提高组 简要题解 玩具迷题(送分) 用异或实现 //@winlere #include<iostream> #include<cstdio> #inc ...
- 「模拟赛 2018-11-02」T3 老大 解题报告
老大 题目描述 因为 OB 今年拿下 4 块金牌,学校赞助扩建劳模办公室为劳模办公室群,为了体现 OI 的特色,办公室群被设计成了树形(n 个点 n − 1 条边的无向连通图),由于新建的办公室太大以 ...
- 1048 数字加密 (20 分)C语言
本题要求实现一种数字加密方法.首先固定一个加密用正整数 A,对任一正整数 B,将其每 1 位数字与 A 的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对 13 取余--这里用 J 代表 ...
- 注解@ConfigurationProperties使用方法
注解@ConfigurationProperties使用方法 前言 最近在思考使用java config的方式进行配置,java config是指基于java配置的spring.传统的Spring一般 ...
- c语言一道题
C语言中,a=b=c,a=b==c,a==(b=c),a==(b==c)有什么区别 main(){inta=1,b=2,c=3;printf("%d,%d,%d,%d\n",a=b ...
- Redis系列之----Redis的两种持久化机制(RDB和AOF)
Redis的两种持久化机制(RDB和AOF) 什么是持久化 Redis的数据是存储在内存中的,内存中的数据随着服务器的重启或者宕机便会不复存在,在生产环境,服务器宕机更是屡见不鲜,所以,我们希望 ...
- Java类成员之代码块
代码块含义:使用{ }括起来的代码 代码块类型: 1.局部代码块:定义在方法体中. 2.构造代码块:也叫初始化代码块,定义在类中方法体之外. 3.静态代码块:定义在类中方法体之外,被static修饰符 ...