博客
关于我
P4313 文理分科
阅读量:796 次
发布时间:2023-02-26

本文共 3608 字,大约阅读时间需要 12 分钟。

网络流解决学科选择问题

在学业选择上,我们有两个主要方向:文科和理科。为了帮助学生做出最佳选择,我们可以使用网络流模型来解决这个问题。网络流是一种强大的工具,可以用来优化资源分配和最大流的问题。

图的构建方法

我们首先需要构建一个网络流图。具体来说,我们采用以下方法:

  • 节点定义

    • S:表示入度为0的源节点。
    • T:表示入度为0的汇节点。
    • ij:分别表示文科和理科的选择节点。
  • 边的连接

    • 从文科节点i到理科节点j,我们创建一条边,权重为art[i][j]。这表示i选择j所需的文科资源。
    • 同样,从理科节点j到文科节点i,我们创建一条边,权重为science[i][j]。这表示j选择i所需的理科资源。
  • 集体加成的处理

    • 当需要考虑集体加成时,我们引入辅助节点(i,j)'
    • S与辅助节点(i,j)'之间的边权重设为sameart[i][j]
    • 同时,将辅助节点(i,j)'与原节点ij之间的边权重设为无穷大(inf)。这样可以确保无论ij是否被选中,辅助节点都不会阻碍流的流动。
  • 通过最大流算法,我们可以从源节点S推出到汇节点T,从而确定最优的学科选择。

    代码实现

    #include 
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #define ll long long#define inf 0x7fffffff#define N 108#define IL inline#define M 100#define D double#define ull unsigned long long#define R registerusing namespace std;template
    IL void read(T &_t) { T __ = 0, ___ = 1; char ____ = getchar(); while (!isdigit(____)) { if (____ == '-') ___ = 0; ____ = getchar(); } while (isdigit(____)) { __ = (__ << 1) + ((__ < 3) ? (____ - '0') : 0); ____ = getchar(); } _t = ___ ? __ : -__;}int n, m, S, T, tot, sum, ans;int to[M], nex[M], head[M], w[M], cur[M];int dep[M], art[N][N], sci[N][N], sart[N][N], saci[N][N];int tx[6] = {0, 1, -1, 0, 0}, ty[6] = {0, 0, 0, 1, -1};queue
    Q;IL int id(int x, int y) { return (x - 1) * m + y;}IL bool safe(int x, int y) { return x >= 1 && x <= n && y >= 1 && y <= m;}IL void add(int x, int y, int z) { to[++tot] = y; nex[tot] = head[x]; head[x] = tot; w[tot] = z; swap(x, y); to[++tot] = y; nex[tot] = head[x]; head[x] = tot; w[tot] = 0;}IL bool bfs() { while (!Q.empty()) Q.pop(); for (R int i = 1; i <= T; ++i) dep[i] = 0; Q.push(S); dep[S] = 1; for (; !Q.empty(); ) { int u = Q.front(); Q.pop(); for (R int i = head[u]; i; nex[i]) { int v = to[i]; if (w[i] > 0 && dep[v] == 0) { dep[v] = dep[u] + 1; Q.push(v); } } } return dep[T] != 0;}IL int dfs(int now, int res) { if (now == T || res == 0) return res; for (R int i = cur[now]; i; nex[i]) { int v = to[i]; if (w[i] > 0 && dep[v] == dep[now] + 1) { int have = dfs(v, min(res, w[i])); if (have > 0) { w[i] -= have; w[i ^ 1] += have; return have; } } } return 0;}IL void Dinic() { while (bfs()) { for (R int i = 1; i <= T; ++i) cur[i] = head[i]; int d = dfs(S, inf); while (d) ans += d, d = dfs(S, inf); }}int main() { // freopen(".in", "r", stdin); // freopen(".out", "w", stdout); read(n); read(m); for (R int i = 1; i <= n; ++i) { for (R int j = 1; j <= m; ++j) { read(art[i][j]); sum += art[i][j]; } } for (R int i = 1; i <= n; ++i) { for (R int j = 1; j <= m; ++j) { read(sci[i][j]); sum += sci[i][j]; } } for (R int i = 1; i <= n; ++i) { for (R int j = 1; j <= m; ++j) { read(sart[i][j]); sum += sart[i][j]; } } for (R int i = 1; i <= n; ++i) { for (R int j = 1; j <= m; ++j) { read(saci[i][j]); sum += saci[i][j]; } } S = 3 * n * m + 1; T = 3 * n * m + 2; for (R int i = 1; i <= n; ++i) { for (R int j = 1; j <= m; ++j) { add(S, id(i, j), art[i][j]); } } for (R int i = 1; i <= n; ++i) { for (R int j = 1; j <= m; ++j) { add(id(i, j), T, sci[i][j]); } } for (R int i = 1; i <= n; ++i) { for (R int j = 1; j <= m; ++j) { add(S, id(i, j) + n * m, sart[i][j]); } } for (R int i = 1; i <= n; ++i) { for (R int j = 1; j <= m; ++j) { for (R int k = 0; k <= 4; ++k) { int cdy = i + tx[k]; int wzy = j + ty[k]; if (safe(cdy, wzy)) { add(id(i, j) + n * m, id(cdy, wzy), inf); add(id(cdy, wzy), id(i, j) + 2 * n * m, inf); } } } } Dinic(); printf("%d\n", sum - ans); // fclose(stdin); // fclose(stdout); return 0;}

    结论

    通过上述方法,我们可以成功地将问题转化为最大流问题,并通过网络流算法找到最优解。这种方法不仅高效,而且能够处理复杂的资源分配问题。

    转载地址:http://dcvfk.baihongyu.com/

    你可能感兴趣的文章
    Oracle流程控制语句
    查看>>
    oracle深度解析检查点
    查看>>
    Oracle游标
    查看>>
    oracle游标数最大数,Oracle 最大连接数 最大游标数
    查看>>
    oracle用户改名
    查看>>
    oracle用户解压不了,PLSQL developer 连接不上64位Oracle 的解决方法
    查看>>
    oracle用户解锁
    查看>>
    Oracle用游标删除重复数据
    查看>>
    Tomcat学习总结(19)—— 为什么首选Tomcat作为JavaWeb应用服务器?
    查看>>
    oracle的内置函数
    查看>>
    Oracle的存储结构
    查看>>
    Oracle的聚合函数group by结合CUBE和ROLLUP的使用
    查看>>
    Oracle监听配置、数据库实例配置等
    查看>>
    Oracle笔记(十三) 视图、同义词、索引
    查看>>
    Oracle笔记(十) 约束
    查看>>
    Oracle系列:安装Oracle RAC数据库(二)
    查看>>
    oracle系统 介绍,ORACLE数据库管理系统介绍
    查看>>
    oracle获取数据库表、字段、注释、约束等
    查看>>
    oracle表空间查询维护命令大全之三(暂时表空间)史上最全
    查看>>
    oracle表访问方式
    查看>>