描述

一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子。每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0)。给定一个起始位置(r,c)

,你可以沿着箭头防线在格子间行走。即如果(r,c)是一个左箭头,那么走到(r,c-1);如果是右箭头那么走到(r,c+1);如果是上箭头那么走到(r-1,c);如果是下箭头那么走到(r+1,c);每一行和每一列都是循环的,即如果走出边界,你会出现在另一侧。

一个完美的循环格是这样定义的:对于任意一个起始位置,你都可以i沿着箭头最终回到起始位置。如果一个循环格不满足完美,你可以随意修改任意一个元素的箭头直到完美。给定一个循环格,你需要计算最少需要修改多少个元素使其完美。

分析

  • 和星际竞速那道题有相通之处. 当时做星际竞速时总结的建模方法在这里用到了.
  • 凡是遇到使每个点都经过一次的题目就可以考虑拆点建图. 拆点, S向Xi连一条容量为1费用为0的边, 表示从X出发. Yi向T连一条容量为1费用为0的边, 表示到达Y.
  • 格子X的Xi向原方向指向的格子Y的Yj连一条容量为INF, 费用为0的边, 向另外三个方向指向的格子连一条容量为INF, 费用为1的边. 表示修改.
代码
#include #include #include #include #include using namespace std; const int INF = 1000000000; const int maxn = 2*15*15 + 10; struct Edge { int from, to, cap, flow, cost; }; struct MCMF { int n, m, s, t; vectoredges; vectorG[maxn]; int inq[maxn], d[maxn], p[maxn], a[maxn]; void init(int n, int s, int t) { this->n = n; this->s = s; this->t = t; } void AddEdge(int from, int to, int cap, int cost) { edges.push_back((Edge){from, to, cap, 0, cost}); edges.push_back((Edge){to, from, 0, 0, -cost}); m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BellmanFord(int& cost) { for(int i = 0; i < n; i++) d[i] = INF; memset(inq, 0, sizeof(inq)); d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF; queueQ; Q.push(s); while(!Q.empty()) { int u = Q.front(); Q.pop(); inq[u] = 0; for(int i = 0; i < G[u].size(); i++) { Edge& e = edges[G[u][i]]; if(e.cap > e.flow && d[e.to] > d[u] + e.cost) { d[e.to] = d[u] + e.cost; p[e.to] = G[u][i]; a[e.to] = min(a[u], e.cap - e.flow); if(!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; } } } } if(d[t] == INF) return false; cost += d[t] * a[t]; int u = t; while(u != s) { edges[p[u]].flow += a[t]; edges[p[u]^1].flow -= a[t]; u = edges[p[u]].from; } return true; } int Mincost() { int cost = 0; while(BellmanFord(cost)); return cost; } }g; int id[maxn][maxn]; int main() { int n, m, s, t; scanf("%d %d", &n, &m); int c = 0; for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) id[i][j] = ++c; g.init(c+c+2, s=0, t=c+c+1); for(int i = 0; i < n; i++) { char str[20]; scanf("%s", str); for(int j = 0; j < m; j++) { g.AddEdge(s, id[i][j], 1, 0); g.AddEdge(id[i][j]+c, t, 1, 0); switch(str[j]) { case 'U': g.AddEdge(id[i][j], id[(i+n-1)%n][j]+c, INF, 0); g.AddEdge(id[i][j], id[(i+1)%n][j]+c, INF, 1); g.AddEdge(id[i][j], id[i][(j+m-1)%m]+c, INF, 1); g.AddEdge(id[i][j], id[i][(j+1)%m]+c, INF, 1); break; case 'D': g.AddEdge(id[i][j], id[(i+n-1)%n][j]+c, INF, 1); g.AddEdge(id[i][j], id[(i+1)%n][j]+c, INF, 0); g.AddEdge(id[i][j], id[i][(j+m-1)%m]+c, INF, 1); g.AddEdge(id[i][j], id[i][(j+1)%m]+c, INF, 1); break; case 'L': g.AddEdge(id[i][j], id[(i+n-1)%n][j]+c, INF, 1); g.AddEdge(id[i][j], id[(i+1)%n][j]+c, INF, 1); g.AddEdge(id[i][j], id[i][(j+m-1)%m]+c, INF, 0); g.AddEdge(id[i][j], id[i][(j+1)%m]+c, INF, 1); break; case 'R': g.AddEdge(id[i][j], id[(i+n-1)%n][j]+c, INF, 1); g.AddEdge(id[i][j], id[(i+1)%n][j]+c, INF, 1); g.AddEdge(id[i][j], id[i][(j+m-1)%m]+c, INF, 1); g.AddEdge(id[i][j], id[i][(j+1)%m]+c, INF, 0); break; } } } printf("%d\n", g.Mincost()); return 0; } 

BZOJ-3171-循环格-TJOI2013-费用流相关推荐

  1. bzoj3171: [Tjoi2013]循环格(费用流)

    传送门 其实这题的建图并不难(虽然我并没有想出来) 首先,每一个点的入度和出度必须为$1$ 那么我们考虑拆点 每个点的出度点向它能到达的点的入度点连边,容量$1$,如果方向为原来的方向则费用$0$否则 ...

  2. BZOJ 5326 [JSOI2017]博弈 (模拟费用流、线段树)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=5326 题解 终于成为第8个A掉这题的人--orz tzw神仙早我6小时 本以为这东西常数 ...

  3. BZOJ 4946: [Noi2017]蔬菜 模拟费用流

    title BZOJ 4946 LUOGU 3826 简化题意: 定义了一种蔬菜为:\(ai,si,ci,xi\),意思是蔬菜的价格为 \(a_i\),第一份卖出时价格为 \(a_i+s_i\),一共 ...

  4. [BZOJ 2424][HAOI2010]订货(费用流)

    Description 某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为 ...

  5. BZOJ 3876 AHOI2014 支线剧情 费用流

    题目大意:给定一张拓扑图,每条边有边权,每次只能从第一个点出发沿着拓扑图走一条路径,求遍历所有边所需要的最小边权和 有下界有源汇的最小费用流 裸的... 建图如下: 对于每一条边权为z的边x-> ...

  6. BZOJ.3265.志愿者招募加强版(费用流SPFA)

    题目链接 见上题. 每类志愿者可能是若干段,不满足那个...全幺模矩阵(全单位模矩阵)的条件,所以线性规划可能存在非整数解. 于是就可以用费用流水过去顺便拿个rank2 233. //20704kb ...

  7. bzoj 2424: [HAOI2010]订货(费用流)

    2424: [HAOI2010]订货 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 784  Solved: 541 [Submit][Status ...

  8. [BZOJ 1070][SCOI2007]修车(费用流)

    Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使 ...

  9. BZOJ 1070: [SCOI2007]修车(费用流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1070 题意: 思路: 神奇的构图. 因为排在后面的人需要等待前面的车修好,这里将每个技术人员拆成n个 ...

  10. 【BZOJ 3171】 [Tjoi2013]循环格

    Description 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位置(r,c) ,你可以沿着箭头防线在格 ...

最新文章

  1. 编写纳新网站后端的相关知识总结
  2. C# 使用正则表达式去掉字符串中的数字
  3. centos 6.5 安装 lamp 后mysql不能启动_CentOS 6.5系统安装配置LAMP(Apache+PHP5+MySQL)服务器环境...
  4. 深入理解Java虚拟机-如何利用VisualVM对高并发项目进行性能分析
  5. 持续集成最佳实践_集成服务性能最佳实践–数据流优化
  6. AttributeError: module ‘onnxruntime‘ has no attribute ‘InferenceSession‘
  7. lodop简单入门教程
  8. at shutdown 不起作用_at胎是什么胎
  9. 犀牛书第七版学习笔记:表达式和运算符
  10. 干货 | 京东云部署Wordpress最佳实践
  11. Excel根据身份证号自动识别性别
  12. 【生信】基因组学相关基础知识2
  13. 两台windows电脑互相备份
  14. 全世界最好听的钢琴曲
  15. 如何在Docker容器中安装RabbitMQ
  16. 方舟服务器延迟n a什么意思,留存分析
  17. iPhone上使用网易云音乐的“我的音乐云盘”
  18. matlab怀特检验,Eviews8.0多元回归后怀特检验有异方差,如何修正?
  19. File Path使用
  20. HTML实现页面过渡

热门文章

  1. 科大星云诗社动态20201118
  2. 雨中赶班车 2019-12-19
  3. 2018 NLP圣经《自然语言处理综述》最新手稿已经发布!
  4. oracle aced什么资质,ACOUG 中国行—暨Oracle WDP云数据之旅,火热报名中……
  5. java写界面_java能不能直接做界面窗口
  6. python读取redis存储数据的存储时间_Python读写Redis数据库操作示例
  7. 用于文档上下文感知推荐的卷积矩阵分解
  8. python字符串与文本处理技巧(2):大小写敏感搜索、最短匹配、多行匹配、Unicode标准化
  9. CMake3:添加一个库
  10. __declspec关键字详细用法