[Tjoi2013]循环格
2014年3月18日1,7500
Description
Input
第一行两个整数R,C。表示行和列,接下来R行,每行C个字符LRUD,表示左右上下。
Output
一个整数,表示最少需要修改多少个元素使得给定的循环格完美
Sample Input
3 4
RRRD
URLL
LRRR
RRRD
URLL
LRRR
Sample Output
2
HINT
1<=R,L<=15
这道题是费用流真的没看出来,每个点只应该有一个出度和一个入度。这一点只要确定了,就可以保证了每个点循环,十分巧妙,然后只要费用流确保每个点如此即可。
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std; const int lx[]={,,,-},ly[]={,,-,};
const int INF=1e9+,NN=**+,MM=; int n,m,S,T;
int cnt,head[NN],next[MM],rea[MM],val[MM],cost[MM];
int dis[NN],flag[NN],a[NN][NN],mark[NN][NN];
char s[];
struct Node
{
int e,fa;
void init(){e=fa=-;}
}pre[NN]; void add(int u,int v,int fee,int fare)
{
cnt++;
next[cnt]=head[u];
head[u]=cnt;
rea[cnt]=v;
val[cnt]=fee;
cost[cnt]=fare;
}
void build()
{
int adq=n*m,nx,ny;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
for (int k=;k<;k++)
{
nx=i+lx[k],ny=j+ly[k];
if (nx<) nx=n;
if (ny<) ny=m;
if (nx>n) nx=;
if (ny>m) ny=;
if (a[i][j]==k) add(mark[i][j],mark[nx][ny]+adq,,),add(mark[nx][ny]+adq,mark[i][j],,);
else add(mark[i][j],mark[nx][ny]+adq,,),add(mark[nx][ny]+adq,mark[i][j],,-);
}
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
{
add(S,mark[i][j],,),add(mark[i][j],S,,);
add(mark[i][j]+adq,T,,),add(T,mark[i][j]+adq,,);
}
}
bool Spfa()
{
for (int i=;i<=T;i++)
{
flag[i]=;
dis[i]=INF;
pre[i].init();
}
queue<int>q;
while (!q.empty()) q.pop();
q.push(S);
dis[S]=,flag[S]=;
while (!q.empty())
{
int u=q.front();
q.pop();
for (int i=head[u];i!=-;i=next[i])
{
int v=rea[i],fee=cost[i];
if (dis[u]+fee<dis[v]&&val[i]>)
{
dis[v]=dis[u]+fee;
pre[v].e=i;
pre[v].fa=u;
if (flag[v]==)
{
flag[v]=;
q.push(v);
}
}
}
flag[u]=;
}
if (dis[T]==INF) return ;
else return ;
}
int MFMC()
{
int res=;
while (Spfa())
{
int x=INF;
for (int i=T;pre[i].fa!=-;i=pre[i].fa)
{
int e=pre[i].e;
x=min(x,val[e]);
}
res+=x*dis[T];
for (int i=T;pre[i].fa!=-;i=pre[i].fa)
{
int e=pre[i].e;
val[e]-=x,val[e^]+=x;
}
}
return res;
}
int main()
{
cnt=;
memset(head,-,sizeof(head));
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
{
scanf("%s",s);
for (int j=;j<m;j++)
{
mark[i][j+]=(i-)*m+j+;
if (s[j]=='R') a[i][j+]=;
if (s[j]=='D') a[i][j+]=;
if (s[j]=='L') a[i][j+]=;
if (s[j]=='U') a[i][j+]=;
}
}
S=n*m*+,T=n*m*+;
build();
printf("%d\n",MFMC());
}