题目大意:

http://www.lydsy.com/JudgeOnline/problem.php?id=3171

题解:

首先我们很容易发现一个结论:

出现完美循环当且仅当所有点的出入度均为1

所以利用这个性质,我们将每个点拆成两个点

S连向出点,入点连向T,然后出点向上下左右的入点连边

跑最小费用最大流即可.

#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
const int maxnode = 512;
const int maxedge = 4096;
struct Edge{
int to,next,cap,cost;
}G[maxedge<<1];
int head[maxnode],cnt=1;
void add(int u,int v,int c,int d){
G[++cnt].to = v;
G[cnt].next = head[u];
head[u] = cnt;
G[cnt].cap = c;
G[cnt].cost = d;
}
inline void insert(int u,int v,int c,int d){
add(u,v,c,d);add(v,u,0,-d);
}
#define v G[i].to
const int lim = maxnode<<1;
int dis[maxnode],p[maxnode],q[lim + 10],flow[maxnode];
int l,r,S,T,ans;bool inq[maxnode];
const int inf = 0x3f3f3f3f;
bool spfa(){
memset(dis,0x3f,sizeof dis);
dis[S] = 0;flow[S] = inf;
inq[S] = true;l = 0;r = -1;
q[++r] = S;
while(l <= r){
int u = q[l % lim];++l;
for(int i = head[u];i;i=G[i].next){
if(dis[v] > dis[u] + G[i].cost && G[i].cap){
dis[v] = dis[u] + G[i].cost;
flow[v] = min(flow[u],G[i].cap);
p[v] = i;
if(!inq[v]){
q[++r % lim] = v;
inq[v] = true;
}
}
}inq[u] = false;
}if(dis[T] == dis[0]) return false;
ans += dis[T]*flow[T];
for(int u = T;u != S;u = G[p[u]^1].to){
G[p[u]].cap -= flow[T],G[p[u]^1].cap += flow[T];
}
return true;
}
#undef v
#define f(x,y) ((x-1)*m + y)
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
inline int id(const char &ch){
if(ch == 'U') return 3;
if(ch == 'D') return 2;
if(ch == 'L') return 1;
if(ch == 'R') return 0;
return -1;
}
int main(){
int n,m;read(n);read(m);
S = maxnode - 5;T = S+1;
char ch;
for(int i=1,x;i<=n;++i){
for(int j=1;j<=m;++j){
insert(f(i,j)<<1,T,1,0);
insert(S,f(i,j)<<1|1,1,0);
while(ch=getchar(),ch<'!');
x = id(ch);if(x == -1) assert(0);
for(int k=0;k<4;++k){
int nx = i + dx[k];if(nx == n+1) nx = 1;if(nx == 0) nx = n;
int ny = j + dy[k];if(ny == m+1) ny = 1;if(ny == 0) ny = m;
insert(f(i,j)<<1|1,f(nx,ny)<<1,1,x != k);
}
}
}
while(spfa());
printf("%d\n",ans);
getchar();getchar();
return 0;
}

bzoj 3171: [Tjoi2013]循环格 最小费用最大流的更多相关文章

  1. BZOJ 3171 [Tjoi2013]循环格(费用流)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3171 [题目大意] 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子. 每 ...

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

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

  3. bzoj 3171 [Tjoi2013]循环格(MCMF)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3171 [题意] 给定一个方向矩阵,要求改变最少的格子,使得任意一个点都在一个环中. [ ...

  4. bzoj 3171: [Tjoi2013]循环格

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

  5. 3171. [TJOI2013]循环格【费用流】

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

  6. BZOJ 2668 [cqoi2012]交换棋子 | 最小费用最大流

    传送门 BZOJ 2668 题解 同时分别限制流入和流出次数,所以把一个点拆成三个:入点in(x).中间点mi(x).出点ou(x). 如果一个格子x在初始状态是黑点,则连(S, mi(x), 1, ...

  7. BZOJ 1061 志愿者招募(最小费用最大流)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1061 题意:申奥成功后,布布经过不懈努力,终于 成为奥组委下属公司人力资源部门的主管.布 ...

  8. bzoj 1070 [SCOI2007]修车(最小费用最大流)

    1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3515  Solved: 1411[Submit][Status] ...

  9. BZOJ 1221: [HNOI2001] 软件开发(最小费用最大流)

    不知道为什么这么慢.... 费用流,拆点.... --------------------------------------------------------------------------- ...

随机推荐

  1. python函数的作用域

    python函数的作用域 以下内容参考自runoob网站,以总结python函数知识点,巩固基础知识,特此鸣谢! 原文地址:http://www.runoob.com/python3/python3- ...

  2. 九度OJ 1195:最长&最短文本 (搜索)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3144 解决:1156 题目描述: 输入多行字符串,请按照原文本中的顺序输出其中最短和最长的字符串,如果最短和最长的字符串不止一个,请全部输 ...

  3. php递归删除所有文件

    function del_file($dir) { if (@rmdir($dir)==false && is_dir($dir)) { if ($dp = opendir($dir) ...

  4. CSS 布局实例系列(一)总结CSS居中的多种方法

    使用 CSS 让页面元素居中可能是我们页面开发中最常见的拦路虎啦,接下来总结一下常见的几种居中方法吧. 1. 首先来聊聊水平居中: text-align 与 inline-block 的配合 就像这样 ...

  5. sqlite增删改查 SimpleCursorAdapter 事务

    <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=&q ...

  6. k近邻算法(k-nearest neighbor,k-NN)

    kNN是一种基本分类与回归方法.k-NN的输入为实例的特征向量,对应于特征空间中的点:输出为实例的类别,可以取多类.k近邻实际上利用训练数据集对特征向量空间进行划分,并作为其分类的"模型&q ...

  7. python __nonzero__方法

    类的nonzero方法用于将类转换为布尔值.通常在用类进行判断和将类转换成布尔值时调用.比如语句if A: print 'foo'中就会调用A.nonzero()来判断.下面这个程序应该能帮助你理解n ...

  8. mssql-在一个特定的会话停止出发器

    用SET CONTEXT_INFO来实现 --在某个会话里设置 SET CONTEXT_INFO 0x8888 --在触发器里判断 ) SELECT @Cinfo = Context_Info() 原 ...

  9. shell脚本默认变量值

    脚本参数相关: $# 是传给脚本的参数个数 $ 是脚本本身的名字 $ 是传递给该shell脚本的第一个参数 $ 是传递给该shell脚本的第二个参数 $@ 是传给脚本的所有参数的列表 $* 是以一个单 ...

  10. memcached监控脚本

    #!/bin/bash . /etc/init.d/functions |wc -l` -lt ];then action "Memcached Serivce is error." ...