bzoj 3171: [Tjoi2013]循环格 最小费用最大流
题目大意:
题解:
首先我们很容易发现一个结论:
出现完美循环当且仅当所有点的出入度均为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]循环格 最小费用最大流的更多相关文章
- BZOJ 3171 [Tjoi2013]循环格(费用流)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3171 [题目大意] 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子. 每 ...
- Bzoj 3171: [Tjoi2013]循环格 费用流
3171: [Tjoi2013]循环格 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 741 Solved: 463[Submit][Status][ ...
- bzoj 3171 [Tjoi2013]循环格(MCMF)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3171 [题意] 给定一个方向矩阵,要求改变最少的格子,使得任意一个点都在一个环中. [ ...
- bzoj 3171: [Tjoi2013]循环格
#include<cstdio> #include<iostream> #include<cstring> #define M 10000 #define inf ...
- 3171. [TJOI2013]循环格【费用流】
Description 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位置(r,c) ,你可以沿着箭头防线在格 ...
- BZOJ 2668 [cqoi2012]交换棋子 | 最小费用最大流
传送门 BZOJ 2668 题解 同时分别限制流入和流出次数,所以把一个点拆成三个:入点in(x).中间点mi(x).出点ou(x). 如果一个格子x在初始状态是黑点,则连(S, mi(x), 1, ...
- BZOJ 1061 志愿者招募(最小费用最大流)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1061 题意:申奥成功后,布布经过不懈努力,终于 成为奥组委下属公司人力资源部门的主管.布 ...
- bzoj 1070 [SCOI2007]修车(最小费用最大流)
1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3515 Solved: 1411[Submit][Status] ...
- BZOJ 1221: [HNOI2001] 软件开发(最小费用最大流)
不知道为什么这么慢.... 费用流,拆点.... --------------------------------------------------------------------------- ...
随机推荐
- Python一些基础练习题
可变的数据类型:list, dict, set(可修改其中的元素) 不可变的数据类型:str, tuple 重点:str, list, dict (1).推导式练习 # 利用列表推导式: 找出100以 ...
- python的协程和_IO操作
协程Coroutine: 协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行. 注意,在一个子程序中中断,去执行其他子程序,不是函数调用,有点 ...
- H5动静分离
1. 动静分离的实现思路(类似于iOS.安卓的思路,后台提供数据接口,前端用ajax异步请求json数据,再把json数据渲染到页面) 动静分离是将网站静态资源(HTML,JavaScript,CSS ...
- 【python】-- 文件操作
一.概述 我们工作中需要经常操作文件,下面就讲讲如何用Python操作文件 1.文件操作的流程: 打开文件,得到文件句柄赋值给一个变量 通过文件句柄,对文件进行操作 关闭文件 #获取文件句柄 f = ...
- centos6安装nginx最详细步骤
第一步:在centos下面下载 nginx wget http://nginx.org/download/nginx-1.2.9.tar.gz 解压 tar zxf nginx-1. ...
- linux 7- - watch,free,mpstat,vmstat,iostat,pidstat,df,du
十八. 和系统运行状况相关的Shell命令: 1. Linux的实时监测命令(watch): watch 是一个非常实用的命令,可以帮你实时监测一个命令的运行结果,省得一遍又一遍的 ...
- MainWindows
开发带有菜单栏状态栏等常用windows应用时候使用
- sql查询报错:Every derived table must have its own alias
执行sql语句出现语法错误 Every derived table must have its own alias 翻译:每个派生表都有自己的别名
- mysql查询当天,本周,本月,上一个月的数据(转)
今天 select * from 表名 where to_days(时间字段名) = to_days(now()); 昨天 SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ...
- 有关java之反射的使用
1 public class Demo02 { 2 @SuppressWarnings("all") 3 public static void main(String[] args ...