题意

有$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. 搭建局域网maven仓库

    第一步: 下载Nexus http://nexus.sonatype.org/downloads/下载最新版本 解压缩到任意目录,我的直接解压到了E盘---------->E:\nexus-2. ...

  2. UBUNTU : Destination Host Unreachable

    介绍我的系统的搭建的方式: WIN7 64 + VMWARE STATION,方式是进行桥接的方式.最近突然出现了问题,Ubuntu ping 外网或者 PING WIN 7 的时候,出现 Desti ...

  3. 导出数据生成Excel(MVC)

    /// <summary> /// 生成Excel /// </summary> /// <returns></returns> public File ...

  4. java Map 实现类的对比

    java为数据结构中的映射定义了一个接口 java.util.Map ,他有四个实现类

  5. Python,Pycharm,Anaconda等的关系与安装过程~为初学者跳过各种坑

    1.致欢迎词 我将详讲讲述在学Python初期的各种手忙脚乱的问题的解决,通过这些步骤的操作,让你的注意力集中在Python的语法上以及后面利用Python所解决的项目问题上.而我自己作为小白,很不幸 ...

  6. 未加载Microsoft.SqlServer.management.sdk.sfc version......

    这个问题卡了我好久,于是决定记录下来,我这里缺失的是Microsoft.SqlServer.management.sdk.sfc version 12.0.0,当然你也可能后面是11开头的, 这个是由 ...

  7. Java8中 Date和LocalDateTime的相互转换

    一.在Java 8中将Date转换为LocalDateTime 方法1: 将Date转换为LocalDatetime,我们可以使用以下方法: 1.从日期获取ZonedDateTime并使用其方法toL ...

  8. 三分钟教你学Git(十二) 之 fast-forward

    什么是fast forward, 顾名思义,就是高速向前进,Git怎么做到高速的呢? 原来假设Git判定能够fast forward的时候,直接改动当前HEAD指针的指向然后再改动当前HEAD指针.说 ...

  9. android -volley-请求数据

    private List<gson.DataBean>arrGson;//请求的数据 //请求数据的方法 public void initData() { RequestQueue mQu ...

  10. SWT经常使用组件

    1button组件(Button) (1)Button组件经常使用样式 SWT.PUSHbutton SWT.CHECK多选button SWT.RADIO单选button SWT.ARROW箭头bu ...