bzoj 3171(费用流)

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



你可能感兴趣的:(bzoj 3171(费用流))