您的位置:首页 > 其它

bzoj 3171(费用流)

2016-05-08 14:11 253 查看

3171: [Tjoi2013]循环格

Time Limit: 1 Sec Memory Limit: 128 MB

Submit: 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 4

RRRD

URLL

LRRR

Sample Output

2

HINT

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

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: