题意

有$n​$个小朋友,给每个人分$1~m​$个糖果,有k个限制 限制形如$(x,y,z)​$ 表示第$x​$个人分到的糖数减去第$y​$个人分到的糖数不大于$z​$,给第$i​$个人$j​$颗糖获得的满意度为$w_{i,j}​$,问总满意度最大值


点$(i,j)$表示第$i$个人分$j$个糖,当这个点属于$s$集合成立,因为是求满意度最大值,所以负权建边,同时加上个最大值$Max$使得满足最大流模板,假设不考虑限制,对于每一个$i$,连边$(i,j)\rightarrow (i,j+1),j\in[1,m)$,边权为$Max-w_i,j$,$s\rightarrow(i,1)$,那么此时的最小割便是能得到最大满意度

对于每个限制,当$x$选了$i$个糖,那么$y$至少要选$i-z$个糖,连边$(x,i)\rightarrow s, i \in [1,m] \land i - z < 1$,或$(x,i)\rightarrow (y,i-z), i \land [1,m] \land 1 \le i - z \le m$ ,或$(x,i)\rightarrow t, i \in [1,m] \land i - z > m$ ,边权为$inf$,这样,当不满足限制的割边发生时,得到的最小割会大于$inf$

关于限制的建边的详细题解:http://blog.csdn.net/wing_wuchen/article/details/77407413

答案为$Max*n-mincut$

代码

#include <bits/stdc++.h>
#define MAXN 300005
#define MAXM 50000005
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
struct Edge {
int to, nxt, c;
}edge[MAXM];
int head[MAXN], cnt = 0;
int d[MAXN], cur[MAXN], pre[MAXN], gap[MAXN];
int source, sink, limit;
void init() {
memset(head, -1, sizeof(head));
cnt = 0;
}
inline void add_edge(int u, int v, int c) {
edge[cnt].to = v;
edge[cnt].nxt = head[u];
edge[cnt].c = c;
head[u] = cnt++;
} inline void add(int u, int v, int c) {
add_edge(u, v, c); add_edge(v, u, 0);
} void rev_bfs() {
memset(gap, 0, sizeof(gap));
memset(d, -1, sizeof(d));
d[sink] = 0;
gap[0] = 1;
queue<int> que;
que.push(sink);
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].to;
if(~d[v])continue;
d[v] = d[u] + 1;
gap[d[v]]++;
que.push(v);
}
}
}
int isap() {
memcpy(cur, head, sizeof(cur));
rev_bfs();
int flow = 0, i;
int u = source;
pre[source] = source;
while(d[sink] < limit) {
if(u == sink) {
int f = inf, neck;
for(i = source; i != sink; i = edge[cur[i]].to) {
if(f > edge[cur[i]].c) {
f = edge[cur[i]].c;
neck = i;
}
}
for(i = source; i != sink; i = edge[cur[i]].to) {
edge[cur[i]].c -= f;
edge[cur[i] ^ 1].c += f;
}
flow += f;
u = neck;
}
for(i = cur[u]; ~i; i = edge[i].nxt) {
if(d[edge[i].to] + 1 == d[u] && edge[i].c) break;
}
if(~i) {
cur[u] = i;
pre[edge[i].to] = u;
u = edge[i].to;
}else {
if((--gap[d[u]]) == 0) break;
int mind = limit;
for(int i = head[u]; ~i; i = edge[i].nxt) {
if(edge[i].c && mind > d[edge[i].to]) {
cur[u] = i;
mind = d[edge[i].to];
}
}
d[u] = mind + 1;
gap[d[u]]++;
u = pre[u];
}
}
return flow;
}
int t, n, m, k, w[100][100], x, y, z;
int get(int x, int y) {return (x - 1) * m + y;}
int main() {
scanf("%d", &t);
while(t--) {
init();
scanf("%d%d%d", &n, &m, &k);
source = 0; sink = n * m + 1; limit = sink + 1;
for(int i = 1; i <= n; ++i) {
add(source, get(i, 1), inf);
for(int j = 1; j <= m; ++j) {
scanf("%d", &w[i][j]);
if(j < m) add(get(i, j), get(i, j + 1), 1000 - w[i][j]);
else add(get(i, j), sink, 1000 - w[i][j]);
}
}
for(int i = 1; i <= k; ++i) {
scanf("%d%d%d", &x, &y, &z);
for(int j = 1; j <= m; ++j) {
if(j - z < 1) add(get(x, j), source, inf);
else if(j - z <= m) add(get(x, j), get(y, j - z), inf);
else add(get(x, j), sink, inf);
}
}
int ans = isap();
if(ans >= inf) printf("-1\n"); else printf("%d\n", 1000 * n - ans);
}
return 0;
}

【HDU 6126】Give out candies 最小割的更多相关文章

  1. HDU 6126.Give out candies 最小割

    Give out candies Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Other ...

  2. hdu 6126 Give out candies

    hdu 6126 Give out candies(最小割) 题意: 有\(n\)个小朋友,标号为\(1\)到\(n\),你要给每个小朋友至少\(1\)个且至多\(m\)个的糖果.小朋友们共提出\(k ...

  3. HDU 4289:Control(最小割)

    http://acm.hdu.edu.cn/showproblem.php?pid=4289 题意:有n个城市,m条无向边,小偷要从s点开始逃到d点,在每个城市安放监控的花费是sa[i],问最小花费可 ...

  4. HDU 3452 Bonsai(网络流之最小割)

    题目地址:HDU 3452 最小割水题. 源点为根节点.再另设一汇点,汇点与叶子连边. 对叶子结点的推断是看度数是否为1. 代码例如以下: #include <iostream> #inc ...

  5. HDU 5889 Barricade 【BFS+最小割 网络流】(2016 ACM/ICPC Asia Regional Qingdao Online)

    Barricade Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  6. HDU 3526 Computer Assembling(最小割)

    http://acm.hdu.edu.cn/showproblem.php?pid=3526 题意:有个屌丝要配置电脑,现在有n个配件需要购买,有两家公司出售这n个配件,还有m个条件是如果配件x和配件 ...

  7. HDU 6214 Smallest Minimum Cut 最小割,权值编码

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6214 题意:求边数最小的割. 解法: 建边的时候每条边权 w = w * (E + 1) + 1; 这 ...

  8. HDU 3251 Being a Hero(最小割+输出割边)

    Problem DescriptionYou are the hero who saved your country. As promised, the king will give you some ...

  9. HDU 3691 Nubulsa Expo(全局最小割)

    Problem DescriptionYou may not hear about Nubulsa, an island country on the Pacific Ocean. Nubulsa i ...

随机推荐

  1. UNP学习笔记(第三章:套接字编程简介)

    本章开始讲解套接字API. 套接字地址结构 IPv4套接字地址结构 它以sockaddr_in命名,下面给出它的POSIX定义 struct in_addr { in_addr_t s_addr; } ...

  2. apue学习笔记(第十章 信号)

    本章先对信号机制进行综述,并说明每种信号的一般用法. 信号概念 每个信号都有一个名字,这些名字都以3个字符SIG开头.在头文件<signal.h>中,信号名都被定义为正整形常量. 在某个信 ...

  3. Hive命令详解

    http://blog.itpub.net/22778222/viewspace-1119892/  官方文档翻译 http://blog.csdn.net/hguisu/article/detail ...

  4. Android学习笔记(36):Android的两种事件处理方式

    Android提供了两种事件处理的方式:基于回调的事件处理 和 基于监听的事件处理. 我们来说的easy理解一点: (1)基于回调的事件处理就是继承GUI组件,并重写该组件的事件处理方法.除了一些特定 ...

  5. C# 中三个关键字params,Ref,out

    一. using System; using System.Collection.Generic; using System.Text; namespace ParamsRefOut { class ...

  6. 提高网站打开速度的7大秘籍---依据Yslow工具的优化【转】

    很多站长使用虚拟主机来做网站,网页内容一旦很多,网站打开速度就会特别慢,如果说服务器.带宽.CDN这类硬指标我们没有经济实力去做,不妨通过网页代码优化的方式来提高速度,卢松松总结了一些可行性的方法. ...

  7. 软件工程第3次作业——Visual Studio 2017下针对代码覆盖率的C/C++单元测试

    本项目Github地址(同时包括两个作业项目): Assignment03 -- https://github.com/Oberon-Zheng/SoftwareEngineeringAssignme ...

  8. 【Selenium + Python】之如何获取最新的报告以及os.path.getmtime与os.path.getctime的区别

    import os def new_file(test_dir): #列举test_dir目录下的所有文件(名),结果以列表形式返回. lists=os.listdir(test_dir) #sort ...

  9. 调整图像的尺寸 - cvResize() 函数实现

    前言 有时会碰到一张图片太大了,想将它缩小.本文将讲解一个很好用的函数解决这个问题. 图像尺寸调整函数 cvResize() // 图像尺寸调整函数 void Resize ( const CvArr ...

  10. C# C/S程序使用HTML文件作为打印模板

    C#   C/S程序使用HTML文件作为打印模板 在网上找了一堆的资料,整理到郁闷呀,慢慢试慢慢改.哎,最终成功了,哈,菜鸟伤不起呀 public partial class Print : Form ...