BZOJ 3171 [Tjoi2013]循环格(费用流)
【题目链接】 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]循环格(费用流)的更多相关文章
- Bzoj 3171: [Tjoi2013]循环格 费用流
3171: [Tjoi2013]循环格 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 741 Solved: 463[Submit][Status][ ...
- bzoj 3171: [Tjoi2013]循环格
#include<cstdio> #include<iostream> #include<cstring> #define M 10000 #define inf ...
- [TJOI2013]循环格 费用流 BZOJ3171
题目背景 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位(r,c),你可以沿着箭头方向在格子间行走.即:如果 ...
- bzoj 3171: [Tjoi2013]循环格 最小费用最大流
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3171 题解: 首先我们很容易发现一个结论: 出现完美循环当且仅当所有点的出入度均为1 所 ...
- bzoj 3171 [Tjoi2013]循环格(MCMF)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3171 [题意] 给定一个方向矩阵,要求改变最少的格子,使得任意一个点都在一个环中. [ ...
- BZOJ 3171 循环格(费用流)
题意 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位置(r,c),你可以沿着箭头防线在格子间行走.即如果(r ...
- 3171. [TJOI2013]循环格【费用流】
Description 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位置(r,c) ,你可以沿着箭头防线在格 ...
- BZOJ_3171_[Tjoi2013]循环格_最小费用最大流
BZOJ_3171_[Tjoi2013]循环格_最小费用最大流 Description 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为 ...
- [Tjoi2013]循环格
[Tjoi2013]循环格 2014年3月18日1,7500 Description Input 第一行两个整数R,C.表示行和列,接下来R行,每行C个字符LRUD,表示左右上下. Output 一个 ...
随机推荐
- LCA入门题集小结
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题目: How far away ? Time Limit: 2000/1000 MS (Jav ...
- fundamentals of the jQuery library
1.why is jquery Only 32kB minified and gzipped. Can also be included as an AMD module Supports CSS3 ...
- js_在原有的日期上添加天数输出添加后的日期
开始编码工作也有段时间了,想想没有留下点什么,有点遗憾.学到的一些经验,写写,分享一下.也给自己整理一下. 今天分享一下,在原有的日期上添加天数输出添加后的日期.开始做的时候,简单的思路是,直接用ne ...
- Msfvenom学习总结-MSF反弹webshell
1. –p (- -payload-options) 添加载荷payload. 载荷这个东西比较多,这个软件就是根据对应的载荷payload生成对应平台下的后门,所以只有选对payload,再填 ...
- 【Python学习笔记】Pandas库之DataFrame
1 简介 DataFrame是Python中Pandas库中的一种数据结构,它类似excel,是一种二维表. 或许说它可能有点像matlab的矩阵,但是matlab的矩阵只能放数值型值(当然matla ...
- 2012年Elsevier旗下Computer Science期刊最新SCI影响因子排名
Latest Impact Factor figures from Elsevier's Computer Science Journals Medical Image Analysis Impact ...
- linux内核启动分析(3)
主要分析do_basic_setup函数里面的do_initcalls()函数,这个函数用来调用所有编译内核的驱动模块中的初始化函数. static void __init do_initcalls( ...
- 【hihocoder】sam-3
把Parent Tree拓扑排序下,然后从下往上合并. 具体的看官方题解啦~ #include<bits/stdc++.h> #define N 1000010 using namespa ...
- 1833: [ZJOI2010]count 数字计数——数位dp
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1833 省选之前来切一道裸的数位dp.. 题意 统计[a,b]中0~9每个数字出现的次数(不算 ...
- linux sort排序命令
1 sort的工作原理 sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出. 2 sort的-u选项 在输出行中去除重复行. $ ...