hoj 2715 (费用流 拆点)

news/2024/12/23 5:31:24/

http://acm.hit.edu.cn/hoj/problem/view?id=2715

将每个格子 i 拆成两个点 i’, i’’并加边(i’, i’’, 1, -Vi), (i’, i’’, ∞, 0), (s, i’, ∞, 0); 控制只有一次能取到宝物。

对相邻的四个格子 j, Hi > Hj 则加边(i’’, j’, ∞, 0);

若格子 i 在边界上则加边(i’’, t, ∞, 0)。

限制增广次数小于等于 K 求最小费用流即可。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <queue>
  6 #include <cmath>
  7 
  8 using namespace std;
  9 
 10 const int maxn = 505;
 11 const int maxm = 2000;
 12 const int inf = 0x3f3f3f3f;
 13 
 14 struct MCMF
 15 {
 16     struct Edge
 17     {
 18         int v, c, w, next;
 19     }p[maxm << 1];
 20     int e, head[maxn], dis[maxn], pre[maxn], cnt[maxn], sumFlow, n;
 21     bool vis[maxn];
 22     void init(int nt)
 23     {
 24         e = 0; n = nt;
 25         memset(head, -1, sizeof(head[0]) * (n + 2) );
 26     }
 27     void addEdge(int u, int v, int c, int w)
 28     {
 29         p[e].v = v; p[e].c = c; p[e].w = w; p[e].next = head[u]; head[u] = e++;
 30         swap(u, v);
 31         p[e].v = v; p[e].c = 0; p[e].w = -w; p[e].next = head[u]; head[u] = e++;
 32     }
 33     bool spfa(int S, int T)
 34     {
 35         queue <int> q;
 36         for (int i = 0; i <= n; ++i)
 37             vis[i] = cnt[i] = 0, pre[i] = -1, dis[i] = inf;
 38         vis[S] = 1, dis[S] = 0;
 39         q.push(S);
 40         while (!q.empty())
 41         {
 42             int u = q.front(); q.pop();
 43             vis[u] = 0;
 44             for (int i = head[u]; i + 1; i = p[i].next)
 45             {
 46                 int v = p[i].v;
 47                 if (p[i].c && dis[v] > dis[u] + p[i].w)
 48                 {
 49                     dis[v] = dis[u] + p[i].w;
 50                     pre[v] = i;
 51                     if (!vis[v])
 52                     {
 53                         q.push(v);
 54                         vis[v] = 1;
 55                         if (++cnt[v] > n) return 0;
 56                     }
 57                 }
 58             }
 59         }
 60         return dis[T] != inf;
 61     }
 62     int mcmf(int S, int T, int kt)
 63     {
 64         sumFlow = 0;
 65         int minFlow = 0, minCost = 0;
 66         while (spfa(S, T) && (kt--))
 67         {
 68             minFlow = inf + 1;
 69             for (int i = pre[T]; i + 1; i = pre[ p[i ^ 1].v ])
 70                 minFlow = min(minFlow, p[i].c);
 71             sumFlow += minFlow;
 72             for (int i = pre[T]; i + 1; i = pre[ p[i ^ 1].v ])
 73             {
 74                 p[i].c -= minFlow;
 75                 p[i ^ 1].c += minFlow;
 76             }
 77             minCost += dis[T] * minFlow;
 78         }
 79         return minCost;
 80     }
 81     void build(int nt, int kt)
 82     {
 83         int nnt = nt * nt;
 84         init(nnt * 2 + 1);
 85         int val[53][53], height[53][53];
 86         memset(val, 0x3f, sizeof(val));
 87         memset(height, 0x3f, sizeof(height));
 88         for (int i = 1; i <= nt; ++i)
 89             for (int j = 1; j <= nt; ++j)
 90                 scanf("%d", &val[i][j]);
 91         for (int i = 1; i <= nt; ++i)
 92             for (int j = 1; j <= nt; ++j)
 93                 scanf("%d", &height[i][j]);
 94         for (int i = 1; i <= nt; ++i)
 95             for (int j = 1; j <= nt; ++j)
 96             {
 97                 int pos = nt * (i - 1) + j;
 98                 addEdge(0, pos, inf, 0);
 99                 addEdge(pos, pos + nnt, 1,-val[i][j]);
100                 addEdge(pos, pos + nnt, inf,0);
101                 if (i == 1 || i == nt || j == 1 || j == nt)
102                     addEdge(pos + nnt, n, inf, 0);
103                 if (height[i][j] > height[i][j - 1])
104                     addEdge(pos + nnt, pos - 1, inf, 0);
105                 if (height[i][j] > height[i][j + 1])
106                     addEdge(pos + nnt, pos + 1, inf, 0);
107                 if (height[i][j] > height[i - 1][j])
108                     addEdge(pos + nnt, pos - nt, inf, 0);
109                 if (height[i][j] > height[i + 1][j])
110                     addEdge(pos + nnt, pos + nt, inf, 0);
111             }
112     }
113     void solve(int nt, int kt)
114     {
115         build(nt, kt);
116         printf("%d\n", - mcmf(0, n, kt));
117     }
118 }my;
119 int main()
120 {
121     int tcase, n, k;
122     scanf("%d", &tcase);
123     while (tcase--)
124     {
125         scanf("%d%d", &n, &k);
126         my.solve(n, k);
127     }
128     return 0;
129 }

 

转载于:https://www.cnblogs.com/Missa/p/3266188.html


http://www.ppmy.cn/news/190339.html

相关文章

HarmonyOS/OpenHarmony按键设备键值

按键设备键值。 作者:坚果整理,欢迎大家加入坚果组织一起学习HarmonyOS/OpenHarmony应用开发 导入模块 import {KeyCode} from @ohos.multimodalInput.keyCode;KeyCode 按键键码值。 名称值说明KEYCODE_FN0功能(Fn)键KEYCODE_UNKNOWN-1未知按键KEYCODE_HOME1功能(Home…

JD2715 忠诚2——线段树

Description 老管家是一个聪明能干的人。他为财主工作了整整10年&#xff0c;财主为了让自已账目更加清楚。要求管家每天记k次账&#xff0c;由于管家聪明能干&#xff0c;因而管家总是让财主十分满意。但是由于一些人的挑拨&#xff0c;财主还是对管家产生了怀疑。于是他决定用…

HOJ - 2715最小费用流

国庆八天乐&#xff0c;刷题也快乐。 HOJ崩了&#xff0c;但是VJ可以把题目挂出来。 题目链接&#xff1a;https://vjudge.net/contest/188441#problem/A 涉及到矩阵里面的网络流&#xff0c;化为图来做。 某个点有流量限制&#xff0c;一定要想到拆点。 求最大值的话&#xff…

HOJ 2715 Matrix3

限制增广次数的费用流。 【题目大意】 一个N*N的网格&#xff0c;每个单元都有一个价值Vi的宝物和一个高度Hi。现在ZhouGuyue要作至多K次旅行&#xff0c;每次旅行如下&#xff1a;他可以借助bin3的直升机飞到任意一个单元&#xff0c;之后他每次只能向相邻的且高度比当前所在格…

洛谷 P2715 约数和

给出a和b求a^b的约数和。 题目描述 输入输出格式 输入格式&#xff1a; 一行两个数a,b。 输出格式&#xff1a; 一个数表示结果对 9901 的模。 输入输出样例 输入样例#1&#xff1a; 2 3 输出样例#1&#xff1a; 15 说明 对于 30%的数据&#xff0c;a,b≤ 10 对于 100%的数据&a…

Dell p2415q DP 如何开启 60hz 模式, Macbook pro 2017

Dell p2415q DP 如何开启 60hz 模式, Macbook pro 2017 注意事项 背面的两个DP接口&#xff0c;一个是输入&#xff0c;一个是输出 靠近电源口的那个 DP 口是视频源输入口&#xff0c;远离电源口的那个是 DP 的输出口。 接输出口是没有效果的&#xff0c;那个口是用于连接多台…

Win10 电脑屏幕亮度随背景颜色变化而变化

Win10 电脑屏幕亮度随背景颜色变化而变化 我的电脑&#xff1a;DELL台式机XPS8700,显示器型号&#xff1a;P2715Q 问题描述&#xff1a; 电脑由WIN7系统升级为WIN10教育版后&#xff0c;查看图片如果图片是暗的&#xff0c;显示器就会慢慢变暗&#xff0c;关掉图片后显示器又…

【3000字帮你深度剖析数据在内存中的存储】

本节重点 -- 重中之重 数据类型详细介绍 整形在内存中的存储&#xff1a;原码、反码、补码 大小端字节序介绍及判断 浮点型在内存中的存储解析 准备好了&#xff0c;开始啰&#xff0c;在小小的花园里面......最近被这个歌曲洗脑&#xff0c;但是我们并不是要唱歌&#xff0c;而…