[Tjoi2013]循环格
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
这道题是费用流真的没看出来,每个点只应该有一个出度和一个入度。这一点只要确定了,就可以保证了每个点循环,十分巧妙,然后只要费用流确保每个点如此即可。
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 ",MFMC()); 129 }