[Tjoi2013]循环格

[Tjoi2013]循环格

Description

Input

第一行两个整数R,C。表示行和列,接下来R行,每行C个字符LRUD,表示左右上下。

Output

一个整数,表示最少需要修改多少个元素使得给定的循环格完美

Sample Input

3 4
RRRD
URLL
LRRR

Sample Output

2

HINT

1<=R,L<=15

这道题是费用流真的没看出来,每个点只应该有一个出度和一个入度。这一点只要确定了,就可以保证了每个点循环,十分巧妙,然后只要费用流确保每个点如此即可。

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<cstring>
  6 #include<queue>
  7 using namespace std;
  8 
  9 const int lx[4]={0,1,0,-1},ly[4]={1,0,-1,0};
 10 const int INF=1e9+7,NN=15*15*2+7,MM=10007;
 11 
 12 int n,m,S,T;
 13 int cnt,head[NN],next[MM],rea[MM],val[MM],cost[MM];
 14 int dis[NN],flag[NN],a[NN][NN],mark[NN][NN];
 15 char s[7];
 16 struct Node
 17 {
 18     int e,fa;
 19     void init(){e=fa=-1;}
 20 }pre[NN];
 21 
 22 void add(int u,int v,int fee,int fare)
 23 {
 24     cnt++;
 25     next[cnt]=head[u];
 26     head[u]=cnt;
 27     rea[cnt]=v;
 28     val[cnt]=fee;
 29     cost[cnt]=fare;
 30 }
 31 void build()
 32 {
 33     int adq=n*m,nx,ny;
 34     for (int i=1;i<=n;i++)
 35         for (int j=1;j<=m;j++)
 36             for (int k=0;k<4;k++)
 37             {
 38                 nx=i+lx[k],ny=j+ly[k];
 39                 if (nx<1) nx=n;
 40                 if (ny<1) ny=m;
 41                 if (nx>n) nx=1;
 42                 if (ny>m) ny=1;
 43                 if (a[i][j]==k) add(mark[i][j],mark[nx][ny]+adq,1,0),add(mark[nx][ny]+adq,mark[i][j],0,0);
 44                 else add(mark[i][j],mark[nx][ny]+adq,1,1),add(mark[nx][ny]+adq,mark[i][j],0,-1);
 45             }
 46     for (int i=1;i<=n;i++)
 47         for (int j=1;j<=m;j++)
 48         {
 49             add(S,mark[i][j],1,0),add(mark[i][j],S,0,0);
 50             add(mark[i][j]+adq,T,1,0),add(T,mark[i][j]+adq,0,0);
 51         }
 52 }
 53 bool Spfa()
 54 {
 55     for (int i=1;i<=T;i++)
 56     {
 57         flag[i]=0;
 58         dis[i]=INF;
 59         pre[i].init();
 60     }
 61     queue<int>q;
 62     while (!q.empty()) q.pop();
 63     q.push(S);
 64     dis[S]=0,flag[S]=1;
 65     while (!q.empty())
 66     {
 67         int u=q.front();
 68         q.pop();
 69         for (int i=head[u];i!=-1;i=next[i])
 70         {
 71             int v=rea[i],fee=cost[i];
 72             if (dis[u]+fee<dis[v]&&val[i]>0)
 73             {
 74                 dis[v]=dis[u]+fee;
 75                 pre[v].e=i;
 76                 pre[v].fa=u;
 77                 if (flag[v]==0)
 78                 {
 79                     flag[v]=1;
 80                     q.push(v);
 81                 }
 82             }
 83         }
 84         flag[u]=0;
 85     }
 86     if (dis[T]==INF) return 0;
 87     else return 1;
 88 }
 89 int MFMC()
 90 {
 91     int res=0;
 92     while (Spfa())
 93     {
 94         int x=INF;
 95         for (int i=T;pre[i].fa!=-1;i=pre[i].fa)
 96         {
 97             int e=pre[i].e;
 98             x=min(x,val[e]);
 99         }
100         res+=x*dis[T];
101         for (int i=T;pre[i].fa!=-1;i=pre[i].fa)
102         {
103             int e=pre[i].e;
104             val[e]-=x,val[e^1]+=x;
105         }
106     }
107     return res;
108 }
109 int main()
110 {
111     cnt=1;
112     memset(head,-1,sizeof(head));
113     scanf("%d%d",&n,&m);
114     for (int i=1;i<=n;i++)
115     {
116         scanf("%s",s);
117         for (int j=0;j<m;j++)
118         {
119             mark[i][j+1]=(i-1)*m+j+1;
120             if (s[j]=='R') a[i][j+1]=0;
121             if (s[j]=='D') a[i][j+1]=1;
122             if (s[j]=='L') a[i][j+1]=2;
123             if (s[j]=='U') a[i][j+1]=3; 
124         }
125     }
126     S=n*m*2+1,T=n*m*2+2;
127     build();
128     printf("%d\n",MFMC());
129 }

 

posted @ 2017-07-25 20:34  Kaiser-  阅读(192)  评论(0编辑  收藏  举报