[bzoj3171]循环格

如果把这个矩阵看成一张图,题目相当于要求每一个点的入度和出度都是1(也就是有很多环),否则指向环的点就无法走回自己了
将所有点拆成两个,S向原来的点流(1,0)的边,拆出来的点向T连(1,0)的边,然后每一个点指向初始方向上的点(1,0)的边,指向非初始方向上(1,1)的边,求最小费用最大流即可(也就是让其满足此条件)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 1005
 4 struct ji{
 5     int nex,to,len,cost;
 6 }edge[N<<2];
 7 queue<int>q;
 8 int E,n,m,x,y,ans,dx[4]={-1,0,0,1},dy[4]={0,-1,1,0},head[N],vis[N],d[N],from[N];
 9 char c[4]={'U','L','R','D'},s[N];
10 int id(int x,int y){
11     return x*m+y+1;
12 }
13 void add(int x,int y,int z,int w){
14     edge[E].nex=head[x];
15     edge[E].to=y;
16     edge[E].len=z;
17     edge[E].cost=w;
18     head[x]=E++;
19     if (E&1)add(y,x,0,-w);
20 }
21 bool spfa(){
22     memset(d,0x3f,sizeof(d));
23     memset(vis,0,sizeof(vis));
24     q.push(0);
25     d[0]=0;
26     while (!q.empty()){
27         int k=q.front();
28         q.pop();
29         for(int i=head[k];i!=-1;i=edge[i].nex){
30             int v=edge[i].to;
31             if ((edge[i].len)&&(d[v]>d[k]+edge[i].cost)){
32                 from[v]=i;
33                 d[v]=d[k]+edge[i].cost;
34                 if (!vis[v]){
35                     vis[v]=1;
36                     q.push(v);
37                 }
38             }
39         }
40         vis[k]=0;
41     }
42     return d[2*n*m+1]<0x3f3f3f3f;
43 }
44 int main(){
45     scanf("%d%d",&n,&m);
46     memset(head,-1,sizeof(head));
47     for(int i=0;i<n;i++)
48         for(int j=0;j<m;j++){
49             add(0,id(i,j),1,0);
50             add(id(i,j)+n*m,2*n*m+1,1,0);
51         }
52     for(int i=0;i<n;i++){
53         scanf("%s",s);
54         for(int j=0;j<m;j++)
55             for(int k=0;k<4;k++){
56                 x=(i+dx[k]+n)%n;
57                 y=(j+dy[k]+m)%m;
58                 add(id(i,j),id(x,y)+n*m,1,(c[k]!=s[j]));
59             }
60     }
61     while (spfa()){
62         ans+=d[2*n*m+1];
63         for(int i=2*n*m+1;i;i=edge[from[i]^1].to){
64             edge[from[i]].len--;
65             edge[from[i]^1].len++;
66         }
67     }
68     printf("%d",ans);
69 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/11836017.html