题目描述:
一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子。每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0)。给定一个起始位置(r,c)
,你可以沿着箭头防线在格子间行走。即如果(r,c)是一个左箭头,那么走到(r,c-1);如果是右箭头那么走到(r,c+1);如果是上箭头那么走到(r-1,c);如果是下箭头那么走到(r+1,c);每一行和每一列都是循环的,即如果走出边界,你会出现在另一侧。
一个完美的循环格是这样定义的:对于任意一个起始位置,你都可以i沿着箭头最终回到起始位置。如果一个循环格不满足完美,你可以随意修改任意一个元素的箭头直到完美。给定一个循环格,你需要计算最少需要修改多少个元素使其完美。
输入:
第一行两个整数R,C。表示行和列,接下来R行,每行C个字符LRUD,表示左右上下。
输出:
一个整数,表示最少需要修改多少个元素使得给定的循环格完美
样例输入:
3 4
RRRD
URLL
LRRR
样例输出:
2
题解:
这题有两种构图方法。首先,两种方法根据出入度都为1来构图。
第一种:
(1)将所有的点拆成两个点,将一个点连向源点S,另一个点连向汇点T,连的边都是容量为1,费用为0的。代表了每个点的出入度都是1 。
(2)一个点向四周的另一类点连出一条容量为1费用为0或1(如果无需修改就是0,否则需要修改就是1)的边。
(3)跑最小费用最大流
第二种:
(1)拆点同上,但连的边的容量为该点原本的入(出)度。
(2)对于每个方格(i, j),我们假设原本连的点为(x,y),那么把这个连向的点的第二类点向其他三个没连的点的第一类点连边,容量为1,费用为1。每个第一类点和第二类点之间都连一条容量为1,费用为0的边。
(3)同第一种
代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue> #ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif #ifdef CT
#define debug(...) printf(__VA_ARGS__)
#define setfile()
#else
#define debug(...)
#define filename ""
#define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout);
#endif #define R register
#define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
#define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
#define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
char B[1 << 15], *S = B, *T = B;
inline int FastIn()
{
R char ch; R int cnt = 0; R bool minus = 0;
while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
ch == '-' ? minus = 1 : cnt = ch - '0';
while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
return minus ? -cnt : cnt;
}
#define maxn 20
#define maxcnt 1010
#define maxm 100010
struct Edge
{
int from, to, w, c;
Edge *next, *rev;
}*last[maxcnt], *prev[maxcnt], e[maxm], *ecnt = e;
int opt[maxn][maxn], id[maxn][maxn], s, t, ans;
int dis[maxcnt];
bool vis[maxcnt];
const int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1};
#define cmod(_a, _b) ((_a) % (_b) == 0 ? (_b) : (_a) % (_b))
inline void link(R int _a, R int _b, R int _w, R int _c)
{
*++ecnt = (Edge) {_a, _b, _w, _c, last[_a], ecnt + 1}; last[_a] = ecnt;
*++ecnt = (Edge) {_b, _a, 0, -_c, last[_b], ecnt - 1}; last[_b] = ecnt;
}
#define INF 23333333
std::queue <int> q;
inline bool spfa()
{
for (R int i = 0; i <= t; ++i) dis[i] = INF;
dis[s] = 0; vis[s] = 1; q.push(s);
while (!q.empty())
{
R int now = q.front(); q.pop();
for (R Edge *iter = last[now]; iter; iter = iter -> next)
{
if (iter -> w && iter -> c + dis[now] < dis[iter -> to])
{
dis[iter -> to] = iter -> c + dis[now];
prev[iter -> to] = iter;
if (!vis[iter -> to])
{
vis[iter -> to] = 1;
q.push(iter -> to);
}
}
}
vis[now] = 0;
}
return dis[t] != INF;
}
inline void mcmf()
{
R int x = INF;
for (R Edge *iter = prev[t]; iter; iter = prev[iter -> from])
cmin(x, iter -> w);
for (R Edge *iter = prev[t]; iter; iter = prev[iter -> from])
{
ans += x * iter -> c;
iter -> w -= x;
iter -> rev -> w += x;
}
}
int main()
{
R int n = FastIn(), m = FastIn(), cnt = 0;
for (R int i = 1; i <= n; ++i)
for (R int j = 1; j <= m; ++j)
{
id[i][j] = ++cnt;
R char ch;
while (ch = getc(), ch < 'A' || ch > 'Z');
if (ch == 'U') opt[i][j] = 0;
if (ch == 'D') opt[i][j] = 1;
if (ch == 'L') opt[i][j] = 2;
if (ch == 'R') opt[i][j] = 3;
}
s = 0; t = cnt << 1 | 1;
for (R int i = 1; i <= n; ++i)
for (R int j = 1; j <= m; ++j)
{
link(s, id[i][j], 1, 0);
link(id[i][j] + cnt, t, 1, 0);
for (R int k = 0; k < 4; ++k)
{
R int nx = i + dx[k], ny = j + dy[k];
link(id[i][j], id[cmod(nx, n)][cmod(ny, m)] + cnt, 1, k == opt[i][j] ? 0 : 1);
}
}
while (spfa()) mcmf();
printf("%d\n",ans );
return 0;
}

【bzoj3171】[Tjoi2013]循环格的更多相关文章

  1. BZOJ3171 Tjoi2013 循环格

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

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

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

  3. Bzoj 3171: [Tjoi2013]循环格 费用流

    3171: [Tjoi2013]循环格 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 741  Solved: 463[Submit][Status][ ...

  4. [Tjoi2013]循环格

    [Tjoi2013]循环格 2014年3月18日1,7500 Description Input 第一行两个整数R,C.表示行和列,接下来R行,每行C个字符LRUD,表示左右上下. Output 一个 ...

  5. 洛谷 P3965 [TJOI2013]循环格 解题报告

    P3965 [TJOI2013]循环格 题目背景 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子. 每个元素有一个坐标(行,列),其中左上角元素坐标为\((0,0)\).给定一个起始位\ ...

  6. BZOJ_3171_[Tjoi2013]循环格_最小费用最大流

    BZOJ_3171_[Tjoi2013]循环格_最小费用最大流 Description 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为 ...

  7. [TJOI2013]循环格 费用流 BZOJ3171

    题目背景 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位(r,c),你可以沿着箭头方向在格子间行走.即:如果 ...

  8. 【BZOJ3171】[TJOI2013] 循环格(网络流)

    点此看题面 大致题意: 给你一个循环格,每个格子有一个方向.问你至少修改多少格子,才能使从每个格子出发都能回到原格子. 建图 这是道网络流题目,主要就是考虑如何建图. 我们可以把每个点拆成两个点,一个 ...

  9. bzoj 3171: [Tjoi2013]循环格

    #include<cstdio> #include<iostream> #include<cstring> #define M 10000 #define inf ...

随机推荐

  1. Linux基本服务

    一.Samba服务 1.下载samba yum install samba -y 2.配置samba文件 vim /etc/samba/smb.conf [ken]path = /test    #等 ...

  2. 20191112 Spring Boot官方文档学习(4.5-4.6)

    4.5.国际化 Spring Boot支持本地化消息,因此您的应用程序可以迎合不同语言首选项的用户.默认情况下,Spring Boot messages在类路径的根目录下查找message resou ...

  3. Python模块unittest

    Python自带一个单元测试框架,unittest模块,用它来做单元测试,它里面封装好了一些校验返回结果的方法和一些用例执行前的初始化操作 在说unittest之前,先说几个概念: TestCase: ...

  4. android adb logcat获取日志文件

    一般情况,可以直接在电脑终端上输入logcat来查看手机运行日志,但是测试工作者为了抓取日志文件来给开发人员,需要把日志导出到特定文件中.如下文. 以小米1s手机为例 步骤1:打开第一个终端窗口 ad ...

  5. vue组件化编程应用2

    写几个小案例来理解vue的组件化编程思想,下面是一个demo. 效果图示: 需求: header部输入任务,进行添加,在list中显示; list中每个item项,鼠标移入时,背景变灰并显示delet ...

  6. spring循环依赖是怎么解决的?

    回答:循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleA,则它们最终反映为一个环. Spring如何解决循环依赖? ...

  7. OpenGL字体绘制

    /* glfont.hpp sdragonx 2019-08-15 00:03:33 opengl字体类,提供初学者参考学习 opengl初始化之后,创建字体 font.init(L"微软雅 ...

  8. 3.golang 的注释

    package main import ( "fmt" "math" ) func main() { fmt.Println(pi(5000)) } // pi ...

  9. RabbitMq学习2-php命令行模式测试rabbitmq

    一.RabbitMQ结构 1.几个概念说明:       Broker:简单来说就是消息队列服务器实体. Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列. Queue:消息队列载体 ...

  10. HDU-1018 BigNumber

    Big Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...