题目大意:

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;
}

最新文章

  1. (实用篇)php支付宝接口用法分析
  2. SQL Server 添加链接服务器
  3. IT技术很好的视频网址
  4. sql语句查询出表里符合条件的第二条记录的方法
  5. 使用supervisor的一些注意事项
  6. AutoCAD.NET二次开发错误集锦
  7. 关于hkcmd.exe造成的和Eclipse之间热键冲突
  8. Mysql 冷备份批处理
  9. C++ Primer笔记9_构造函数_拷贝构造(深拷贝与浅拷贝)
  10. Object-C 重载
  11. GitLab版本管理(转)
  12. OC语言(六)
  13. docker 恶意镜像到容器逃逸影响本机
  14. Neural Network Virtual Machine
  15. 【转】导致SQL执行慢的原因
  16. Salesforce的数据安全防护措施
  17. Fortify Scan - Static Code Analyzer
  18. 步步为营-72-asp.net简单练习(通过webForm实现一些简单实例)
  19. linux 常见基础知识(此文章将会在整个linux学习过程中,不断添加)
  20. Windows2003系统如何设置能让两个人共用一个桌面同时远程控制?

热门文章

  1. Entity Framework(1)——Connections and Models
  2. 解决不同浏览器创建不同 XMLHTTP 对象的问题
  3. vue组件父子组件之间传递数据
  4. 我的Android进阶之旅------>介绍一款集录制与剪辑为一体的屏幕GIF 动画制作工具 GifCam
  5. Spring 拦截器——HandlerInterceptor
  6. 扣出thinkphp数据库操作类
  7. c# 文件IO操作 StreamReader StreamWriter Split 使用
  8. spring-boot2
  9. uCGUI 按键窗口切换机制
  10. 第三篇 css属性