bzoj 3171(费用流)
2016-05-08 14:11
253 查看
3171: [Tjoi2013]循环格
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 785 Solved: 493
[Submit][Status][Discuss]
Description
一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子。每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0)。给定一个起始位置(r,c),你可以沿着箭头防线在格子间行走。即如果(r,c)是一个左箭头,那么走到(r,c-1);如果是右箭头那么走到(r,c+1);如果是上箭头那么走到(r-1,c);如果是下箭头那么走到(r+1,c);每一行和每一列都是循环的,即如果走出边界,你会出现在另一侧。
一个完美的循环格是这样定义的:对于任意一个起始位置,你都可以i沿着箭头最终回到起始位置。如果一个循环格不满足完美,你可以随意修改任意一个元素的箭头直到完美。给定一个循环格,你需要计算最少需要修改多少个元素使其完美。
Input
第一行两个整数R,C。表示行和列,接下来R行,每行C个字符LRUD,表示左右上下。Output
一个整数,表示最少需要修改多少个元素使得给定的循环格完美Sample Input
3 4RRRD
URLL
LRRR
Sample Output
2HINT
1<=R,L<=15解题思路:先建图S向每个点连容量1费用0的边
每个点拆出的点向T连容量1,费用0的边
每个格子向四周连费用0或1的边,然后费用流
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int n,m,len,T,ans,S;
int from[1000001],to[1000001],next[1000001],flow[1000001],w[1000001],h[2000];
bool b[2000];
int dis[2000],q[200000];
int pre[2000];
char c[100];
int u[5][3]={0,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1};
inline int read()
{
char y; int x=0,f=1; y=getchar();
while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}
while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
return x*f;
}
void insert(int x,int y,int f,int z)
{
++len; from[len]=x; to[len]=y; next[len]=h[x]; h[x]=len; flow[len]=f; w[len]=z;
}
bool spfa()
{
memset(b,true,sizeof(b));
memset(dis,0x7f,sizeof(dis)); dis[S]=0;
int tail=1,head=0; ++tail; q[tail]=S; b[S]=false;
while (head<tail)
{
++head;
int u=h[q[head]];
while (u!=0)
{
if (w[u]+dis[q[head]]<dis[to[u]] && flow[u]>0)
{
dis[to[u]]=dis[q[head]]+w[u];
pre[to[u]]=u;
if (b[to[u]])
{
b[to[u]]=false;
++tail; q[tail]=to[u];
}
}
u=next[u];
}
b[q[head]]=true;
}
if (dis[T]<14000000) return true;else return false;
}
void get()
{
int now=T; int mx=0x7fffffff;
while (now!=S)
{
mx=min(mx,flow[pre[now]]);
now=from[pre[now]];
}
now=T;
while (now!=S)
{
ans+=mx*w[pre[now]];
flow[pre[now]]-=mx; flow[pre[now]^1]+=mx;
now=from[pre[now]];
}
}
int main()
{
len=1; S=0;
n=read(); m=read(); T=n*m*2+1; int opp=n*m;
for (int i=1;i<=n;++i)
{
scanf("%s",c);
for (int j=1;j<=m;++j)
{
int op=(i-1)*m+j; insert(S,op,1,0); insert(op,S,0,0); insert(op+opp,T,1,0); insert(T,op+opp,0,0);
int u1=i;int u2=j;
if (c[j-1]=='R'){++u2;}
if (c[j-1]=='L'){--u2;}
if (c[j-1]=='U'){--u1;}
if (c[j-1]=='D'){++u1;}
u1=u1%n; u2=u2%m;
if (u1==0) u1=n; if (u2==0) u2=m;
for (int k=1;k<=4;++k)
{
int x1=(i+u[k][1])%n; int y1=(j+u[k][2])%m;
if (x1==0) x1=n; if (y1==0) y1=m;
int now=(x1-1)*m+y1;
if (x1==u1 && y1==u2)
{
insert(op,now+opp,1,0); insert(now+opp,op,0,0);
}else
{
insert(op,now+opp,1,1); insert(now+opp,op,0,-1);
}
}
}
}
ans=0;
while (spfa())
{
get();
}
printf("%d",ans);
}
相关文章推荐
- Android项目无法运行的解决方法
- facebook 15个你必须知道的开源项目
- leetcode 086 Partition List
- Vagrant搭建Ubuntu-JavaEE开发环境——Tomcat+JDK+MySQL+dubbo+测试
- Android 最火的快速开发框架androidannotations配置详解
- struts2进行多文件上传
- Python 迭代工具
- onmousedown,onmouseup,onclick同时应用于一个标签节点Element
- 我的目标
- 常用排序算法总结(三)
- linux curl命令详解
- java设计模式之模板模式
- Ext.grid.Panel中stateId的作用
- poj1068Parencodings
- HashMap实现原理分析
- Android Gradle Plugin指南(二)——基本项目
- java中的集合类(Collection)中的Set
- Search in Rotated Sorted Array
- Linux date命令详解
- NetAnalyzer2016使用方法