题面:中文题面,这里不占用篇幅
分析:
看到题面,我就想弃疗……
但是作为任务题单,还是抄了题解……
大概就是将每个格子拆点,拆成五个点,上下左右的触点和一个负责连源汇点的点(以下简称本点)。
这个这个本点要根据初始形态向相应的触点连接费用为0容量为1的边,再由旋转规则,使初始触点向相应的触点连接费用为旋转次数的边,然后相邻的格子触点相连?
反正很乱就是了。如果再写一遍,我应该不会写罢……
代码:(这份代码在Luogu上不开O2会TLE十八组数据……开了才能过,在loj是可过的)
1 #include<bits/stdc++.h> 2 #define up(u) u+tn*sm 3 #define ri(u) u+((tn+1)&3)*sm 4 #define dn(u) u+((tn+2)&3)*sm 5 #define le(u) u+((tn+3)&3)*sm 6 #define md(u) u+(sm<<2) 7 using namespace std;queue<int>q; 8 const int N=20005,M=200005,inf=0x3f3f3f3f; 9 struct node{int y,z,f,nxt;}e[M]; 10 int mf=0,f[N],lst[N],ans=0;bool vis[N]; 11 int sm,c=1,S=0,T,h[N],d[N],pre[N],n,m,k; 12 void add(int x,int y,int f,int z,int tp){ 13 if(tp) swap(x,y); 14 e[++c]=(node){y,z,f,h[x]};h[x]=c; 15 e[++c]=(node){x,-z,0,h[y]};h[y]=c; 16 } bool spfa(){ 17 for(int i=S;i<=T;i++) pre[i]=-1, 18 f[i]=inf,lst[i]=vis[i]=0,d[i]=inf; 19 q.push(S);d[S]=0;pre[S]=0; 20 while(q.size()){ 21 int x=q.front();q.pop();vis[x]=0; 22 for(int i=h[x],y;i;i=e[i].nxt) 23 if(d[y=e[i].y]>d[x]+e[i].z&&e[i].f){ 24 d[y]=d[x]+e[i].z;pre[y]=x;lst[y]=i; 25 f[y]=min(f[x],e[i].f); 26 if(!vis[y]) vis[y]=1,q.push(y); 27 } 28 } return (pre[T]!=-1); 29 } void solve(){ 30 while(spfa()){ 31 ans+=d[T]*f[T];int x=T;mf+=f[T]; 32 while(x) e[lst[x]].f-=f[T], 33 e[lst[x]^1].f+=f[T],x=pre[x]; 34 } return ; 35 } int main(){ 36 k=1;int t,sp,tn,tf=0,mc=0; 37 scanf("%d%d",&n,&m);sm=n*m;T=sm*5+1; 38 for(int i=0;i<n;i++) 39 for(int j=0;j<m;j++,k++){ 40 tn=0;t=(i+j)&1; 41 if(t) add(S,md(k),inf,0,0); 42 else add(md(k),T,inf,0,0); 43 if(i) add(dn(k-m),up(k),1,0,t); 44 if(j) add(ri(k-1),le(k),1,0,t); 45 scanf("%d",&sp); 46 if(sp&1) add(up(k),md(k),1,0,t),tf++; 47 if(sp&2) add(ri(k),md(k),1,0,t),tf++; 48 if(sp&4) add(dn(k),md(k),1,0,t),tf++; 49 if(sp&8) add(le(k),md(k),1,0,t),tf++; 50 switch(sp){ 51 case 8:tn++; 52 case 4:tn++; 53 case 2:tn++; 54 case 1: 55 add(ri(k),up(k),1,1,t); 56 add(dn(k),up(k),1,2,t); 57 add(le(k),up(k),1,1,t);break; 58 case 9:tn++; 59 case 12:tn++; 60 case 6:tn++; 61 case 3: 62 add(dn(k),up(k),1,1,t); 63 add(le(k),ri(k),1,1,t);break; 64 case 13:tn++; 65 case 14:tn++; 66 case 7:tn++; 67 case 11: 68 add(dn(k),le(k),1,1,t); 69 add(dn(k),up(k),1,2,t); 70 add(dn(k),ri(k),1,1,t);break; 71 } 72 } solve(); 73 printf("%d",tf==mf<<1?ans:-1);return 0; 74 }