CQOI2012 交换棋子

来源:互联网 发布:淘宝店铺免费营销工具 编辑:程序博客网 时间:2024/05/13 18:56

现在艹道水题都要半小时+=感觉整个人都不好了

把点拆掉就可以了=因为次数限制在格子上

又因为走进走出要2次直接÷2=想想头和尾只踩了一次所以除以2前先+1就好了

#include <bits/stdc++.h>#define rep(j,k,l) for (int j=k;j<=l;++j)#define K 22#define N 805#define M 50005using namespace std;int to[M],ne[M],rest[M],cost[M],st[N],a[K][K],b[K][K],c[K][K];int dis[N],f[N],que[N],used[N],last[N],road[N];int n,m,cnt=1,ct1,ct2,head,tail,ans,fee;void add(int k,int l,int o,int p){to[++cnt]=l;ne[cnt]=st[k];st[k]=cnt;rest[cnt]=o;cost[cnt]=p;}bool Spfa(){rep(i,0,n) dis[i]=100000,f[i]=0;f[0]=1;dis[0]=0;head=0;tail=1;que[1]=0;used[0]=1;while (head!=tail){head=(head+1)%N;int x=que[head];used[x]=0;for (int i=st[x];i;i=ne[i])if (rest[i]&&dis[to[i]]>dis[x]+cost[i]){dis[to[i]]=dis[x]+cost[i];f[to[i]]=1;road[to[i]]=i;last[to[i]]=x;if (!used[to[i]]){tail=(tail+1)%N;que[tail]=to[i];used[to[i]]=1;}}}return f[n];}void rset(int k){if (k!=0) rset(last[k]);rest[road[k]]--;rest[road[k]^1]++;}int main(){scanf("%d%d",&n,&m);rep(i,1,n) rep(j,1,m){char ch=getchar();while (ch<48||ch>57) ch=getchar();a[i][j]=ch-48;if (a[i][j]){c[i][j]++;add(0,(i-1)*m+j,1,0);add((i-1)*m+j,0,0,0);ct1++;}}rep(i,1,n) rep(j,1,m){char ch=getchar();while (ch<48||ch>57) ch=getchar();b[i][j]=ch-48;if (b[i][j]){c[i][j]++;add((i-1)*m+j+n*m,n*m*2+1,1,0);add(n*m*2+1,(i-1)*m+j+n*m,0,0);ct2++;}}if (ct1!=ct2){printf("-1\n");return 0;}rep(i,1,n) rep(j,1,m){char ch=getchar();while (ch<48||ch>57) ch=getchar();c[i][j]=(c[i][j]+ch-48)/2;add((i-1)*m+j,(i-1)*m+j+n*m,c[i][j],0);add((i-1)*m+j+n*m,(i-1)*m+j,0,0);if (i>1){add((i-1)*m+j+n*m,(i-2)*m+j,100000,1);add((i-2)*m+j,(i-1)*m+j+n*m,0,-1);}if (j>1){add((i-1)*m+j+n*m,(i-1)*m+j-1,100000,1);add((i-1)*m+j-1,(i-1)*m+j+n*m,0,-1);}if (i<n){add((i-1)*m+j+n*m,i*m+j,100000,1);add(i*m+j,(i-1)*m+j+n*m,0,-1);}if (j<m){add((i-1)*m+j+n*m,(i-1)*m+j+1,100000,1);add((i-1)*m+j+1,(i-1)*m+j+n*m,0,-1);}if (i>1&&j>1){add((i-1)*m+j+n*m,(i-2)*m+j-1,100000,1);add((i-2)*m+j-1,(i-1)*m+j+n*m,0,-1);}if (i<n&&j>1){add((i-1)*m+j+n*m,i*m+j-1,100000,1);add(i*m+j-1,(i-1)*m+j+n*m,0,-1);}if (i>1&&j<m){add((i-1)*m+j+n*m,(i-2)*m+j+1,100000,1);add((i-2)*m+j+1,(i-1)*m+j+n*m,0,-1);}if (i<n&&j<m){add((i-1)*m+j+n*m,i*m+j+1,100000,1);add(i*m+j+1,(i-1)*m+j+n*m,0,-1);}}n=n*m*2+1;while (Spfa()){ans+=f[n];fee+=f[n]*dis[n];rset(n);}if (ans!=ct1) printf("-1\n");else printf("%d\n",fee);return 0;}


0 0