题意

有$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. 获取服务器classes根路径

    /** * 获取web应用路径 * @Description : 方法描述 * @Method_Name : getRootPath * @return * @return : String * @C ...

  2. nfs部署和优化 -2

    客户端: cat /etc/passwd 显示用户 weifeng 500   服务端: vim /etc/exports /mnt 192.168.1.105(rw,sync,all_squash, ...

  3. 导出txt格式的说明书

    /// <summary> /// 说明书 /// </summary> /// <returns></returns> public FileResu ...

  4. C#各种导入Excel文件的数据的方法总结

    在导入前都需要将上传的文件保存到服务器,所以避免重复的写这些代码,先贴出上传文件并保存到服务器指定路径的代码 protected void btnImport_Click(object sender, ...

  5. No bean named &#39;cxf&#39; is defined

    1.错误描写叙述  严重:Exception starting filter CXFServlet        org.springframework.beans.factory.NoSuchBea ...

  6. css3动画学习资料整理

    现在主流浏览器(先不管IE8,IE9吧),尤其是移动端浏览器基本都支持css3了,为了增强页面的表现力,css3动画必不可少了.这篇文章主要整理一下我在学习css3动画所查阅的一些好的资料,并附上两个 ...

  7. 畅通project再续 HDU杭电1875 【Kruscal算法 || Prim】

    Problem Description 相信大家都听说一个"百岛湖"的地方吧.百岛湖的居民生活在不同的小岛中.当他们想去其它的小岛时都要通过划小船来实现.如今政府决定大力发展百岛湖 ...

  8. HDFS源码分析数据块复制监控线程ReplicationMonitor(一)

    ReplicationMonitor是HDFS中关于数据块复制的监控线程,它的主要作用就是计算DataNode工作,并将复制请求超时的块重新加入到待调度队列.其定义及作为线程核心的run()方法如下: ...

  9. java和erlang之间的DES加解密

    app登录,登录的密码要用DES加密,服务器是用erlang,客户端要同时支持多平台(Android.iOS).首先,Java端的DES加密的实现方式, 少说废话了,直接上代码,如下: public ...

  10. os如何处理键盘的所有按键,显示or不显示,显示是如何显示

    [0]README 0.1) source code and text decription are from orange's implemention of a os , and for comp ...