【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=3171

【题目大意】

  一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子。
  每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0)。给定一个起始位置(r,c)
  你可以沿着箭头防线在格子间行走。即如果(r,c)是一个左箭头,那么走到(r,c-1);
  如果是右箭头那么走到(r,c+1);如果是上箭头那么走到(r-1,c);
  如果是下箭头那么走到(r+1,c);每一行和每一列都是循环的,
  即如果走出边界,你会出现在另一侧。一个完美的循环格是这样定义的:
  对于任意一个起始位置,你都可以i沿着箭头最终回到起始位置。
  如果一个循环格不满足完美,你可以随意修改任意一个元素的箭头直到完美。
  给定一个循环格,你需要计算最少需要修改多少个元素使其完美。

【题解】

  我们发现一个完美的循环格每个元素都只有一个入度和一个出度,
  因此我们将其拆分为入点和出现,入点连汇点,出点连源点,流量为1,费用为0,
  对于每个箭头指向的反向,连相应的出点到入点,流量为1,费用为0,
  对于相邻但是箭头不指向的地方,我们将其相互连接,流量为1,费用为1,
  求最小费用最大流即答案。

【代码】

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF=0x7fffffff,N=1010;
int S,T,cnt,ans,d[N],q[N],from[N],g[N],flow,tot;
bool in[1010];
struct edge{int from,to,nxt,c,v;}e[100010];
void add(int u,int v,int w,int c){
e[++cnt].from=u;e[cnt].to=v;
e[cnt].nxt=g[u];g[u]=cnt;
e[cnt].c=c;e[cnt].v=w;
}void add_edge(int u,int v,int w,int c){add(u,v,w,c);add(v,u,0,-c);}
bool spfa(){
for(int i=S;i<=T;i++)d[i]=INF;
int t=0,w=1;d[S]=0;in[S]=1;q[0]=S;
while(t!=w){
int now=q[t];t++;if(t==T)t=0;
for(int i=g[now];i;i=e[i].nxt)
if(e[i].v&&d[e[i].to]>d[now]+e[i].c){
d[e[i].to]=d[now]+e[i].c;from[e[i].to]=i;
if(!in[e[i].to]){in[e[i].to]=1;q[w++]=e[i].to;if(w==T)w=0;}
}in[now]=0;
}return(d[T]!=INF);
}
void mcf(){
int x=INF;
for(int i=from[T];i;i=from[e[i].from])x=min(x,e[i].v);flow+=x;
for(int i=from[T];i;i=from[e[i].from]){e[i].v-=x;e[i^1].v+=x;ans+=e[i].c*x;}
}
const int dx[]={1,-1,0,0},dy[]={0,0,1,-1};
int R,C,mp[20][20];
char str[20][20];
int main(){
while(~scanf("%d%d",&R,&C)){
memset(g,0,sizeof(g));
cnt=1; ans=flow=0;
S=0,T=C*R*2+1;
for(int i=1;i<=R;i++)scanf("%s",str[i]+1);
for(int i=1;i<=R;i++)for(int j=1;j<=C;j++){
if(str[i][j]=='U')mp[i][j]=1;
if(str[i][j]=='D')mp[i][j]=0;
if(str[i][j]=='L')mp[i][j]=3;
if(str[i][j]=='R')mp[i][j]=2;
for(int k=0;k<4;k++){
int x=i+dx[k],y=j+dy[k];
if(x>R)x=1;if(x<1)x=R;
if(y>C)y=1;if(y<1)y=C;
if(k==mp[i][j])add_edge((i-1)*C+j,(x-1)*C+y+C*R,1,0);
else add_edge((i-1)*C+j,(x-1)*C+y+C*R,1,1);
}add_edge(S,(i-1)*C+j,1,0);
add_edge((i-1)*C+j+C*R,T,1,0);
}while(spfa())mcf();
printf("%d\n",ans);
}return 0;
}

BZOJ 3171 [Tjoi2013]循环格(费用流)的更多相关文章

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

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

  2. bzoj 3171: [Tjoi2013]循环格

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

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

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

  4. bzoj 3171: [Tjoi2013]循环格 最小费用最大流

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3171 题解: 首先我们很容易发现一个结论: 出现完美循环当且仅当所有点的出入度均为1 所 ...

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

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

  6. BZOJ 3171 循环格(费用流)

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

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

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

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

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

  9. [Tjoi2013]循环格

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

随机推荐

  1. LCA入门题集小结

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题目: How far away ? Time Limit: 2000/1000 MS (Jav ...

  2. fundamentals of the jQuery library

    1.why is jquery Only 32kB minified and gzipped. Can also be included as an AMD module Supports CSS3 ...

  3. js_在原有的日期上添加天数输出添加后的日期

    开始编码工作也有段时间了,想想没有留下点什么,有点遗憾.学到的一些经验,写写,分享一下.也给自己整理一下. 今天分享一下,在原有的日期上添加天数输出添加后的日期.开始做的时候,简单的思路是,直接用ne ...

  4. Msfvenom学习总结-MSF反弹webshell

    1.    –p (- -payload-options) 添加载荷payload. 载荷这个东西比较多,这个软件就是根据对应的载荷payload生成对应平台下的后门,所以只有选对payload,再填 ...

  5. 【Python学习笔记】Pandas库之DataFrame

    1 简介 DataFrame是Python中Pandas库中的一种数据结构,它类似excel,是一种二维表. 或许说它可能有点像matlab的矩阵,但是matlab的矩阵只能放数值型值(当然matla ...

  6. 2012年Elsevier旗下Computer Science期刊最新SCI影响因子排名

    Latest Impact Factor figures from Elsevier's Computer Science Journals Medical Image Analysis Impact ...

  7. linux内核启动分析(3)

    主要分析do_basic_setup函数里面的do_initcalls()函数,这个函数用来调用所有编译内核的驱动模块中的初始化函数. static void __init do_initcalls( ...

  8. 【hihocoder】sam-3

    把Parent Tree拓扑排序下,然后从下往上合并. 具体的看官方题解啦~ #include<bits/stdc++.h> #define N 1000010 using namespa ...

  9. 1833: [ZJOI2010]count 数字计数——数位dp

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1833 省选之前来切一道裸的数位dp.. 题意 统计[a,b]中0~9每个数字出现的次数(不算 ...

  10. linux sort排序命令

    1 sort的工作原理 sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出. 2 sort的-u选项 在输出行中去除重复行. $ ...