【BZOJ】【2668】【CQOI2012】交换棋子
2015-03-20 18:00
190 查看
网络流/费用流
跪跪跪,居然还可以这样建图……题解:/article/6145383.html
考虑每个点的交换限制的约束,一看就知道是点容量,但是这里不是一分为二,而是一分为三。
首先我们把问题化简,变成对于原图上所有黑点,找到一个新图中的黑点,进行多次交换后到达。我们看到多次交换实际上是走了一条路径(这里不是最短 路)。对于这条路径的起点和终点,仅进行了1次交换,而路径上的其他点都交换了2次。所以我们需要构造一种图来把这个交换次数的差异体现出来,于是:
对于每个点一分为三,分为p0,p1,p2,对于每个点,如果它是原图中得黑点,连 边<p1,p0,c/2,0>,<p0,p2,(c+1)/2>,<st,p0,1,0>;如果它是新图中得黑点, 连边<p1,p0,(c+1)/2>,<p0,p2,c/2,0>,<p0,ed,1,0>;如果它在两个图中都是 白点,那么连边<p1,p0,c/2,0>,<p0,p2,c/2,0>。这样就可以体现出点容量的差异了。
然后对于原图中可以交换的两个点(i,j)连接<pi2,pj1,inf,1>,那么这种边每流过1的流量就意味着(i,j)交换了一次,那么费用就是最终的答案了。
/************************************************************** Problem: 2668 User: Tunix Language: C++ Result: Accepted Time:24 ms Memory:48464 kb ****************************************************************/ //BZOJ 2668 #include<cmath> #include<vector> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define rep(i,n) for(int i=0;i<n;++i) #define F(i,j,n) for(int i=j;i<=n;++i) #define D(i,j,n) for(int i=j;i>=n;--i) #define pb push_back using namespace std; inline int getint(){ int v=0,sign=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} return v*sign; } const int N=20010,M=2000000,INF=~0u>>2; typedef long long LL; /******************tamplate*********************/ char s1[50][50],s2[50][50],s3[50][50]; int n,m,a[50][50],b[50][50],c[50][50],num[50][50],b1,b2,ans,flow,tot; inline int gcd(int a,int b){return b ? gcd(b,a%b) : a;} bool judge(int x,int y){ int q=x*x-y*y,s=sqrt(q); if (s*s==q && gcd(y,s)==1) return 1; return 0; } struct edge{int from,to,v,c;}; struct Net{ edge E[M]; int head ,next[M],cnt; void ins(int x,int y,int z,int c){ E[++cnt]=(edge){x,y,z,c}; next[cnt]=head[x]; head[x]=cnt; } void add(int x,int y,int z,int c){ ins(x,y,z,c); ins(y,x,0,-c); } int from ,Q[M],d ,S,T; bool inq ; bool spfa(){ int l=0,r=-1; F(i,0,T) d[i]=INF; d[S]=0; Q[++r]=S; inq[S]=1; while(l<=r){ int x=Q[l++]; inq[x]=0; for(int i=head[x];i;i=next[i]) if(E[i].v>0 && d[x]+E[i].c<d[E[i].to]){ d[E[i].to]=d[x]+E[i].c; from[E[i].to]=i; if (!inq[E[i].to]){ Q[++r]=E[i].to; inq[E[i].to]=1; } } } return d[T]!=INF; } void mcf(){ int x=INF,y,z; for(int i=from[T];i;i=from[E[i].from]) x=min(x,E[i].v); for(int i=from[T];i;i=from[E[i].from]){ E[i].v-=x; E[i^1].v+=x; } flow+=x; ans+=x*d[T]; } void init(){ n=getint(); m=getint(); cnt=1; tot=n*m; S=0; T=tot*3+1; F(i,1,n) scanf("%s",s1[i]+1); F(i,1,n) scanf("%s",s2[i]+1); F(i,1,n) scanf("%s",s3[i]+1); F(i,1,n) F(j,1,m){ a[i][j]=s1[i][j]-'0'; if(a[i][j]) b1++; b[i][j]=s2[i][j]-'0'; if(b[i][j]) b2++; c[i][j]=s3[i][j]-'0'; if (a[i][j]&&b[i][j]) a[i][j]=b[i][j]=0,b1--,b2--; } F(i,1,n) F(j,1,m){ int now=(i-1)*m+j; num[i][j]=now; if (a[i][j]){ add(S,now,1,0); add(tot+now,now,c[i][j]/2,0); add(now,2*tot+now,(c[i][j]+1)/2,0); }else if(b[i][j]){ add(now,T,1,0); add(tot+now,now,(c[i][j]+1)/2,0); add(now,2*tot+now,c[i][j]/2,0); }else{ add(tot+now,now,c[i][j]/2,0); add(now,2*tot+now,c[i][j]/2,0); } } F(i,1,n) F(j,1,m){ if (i>1) add(2*tot+num[i][j],tot+num[i-1][j],INF,1); if (j>1) add(2*tot+num[i][j],tot+num[i][j-1],INF,1); if (i<n) add(2*tot+num[i][j],tot+num[i+1][j],INF,1); if (j<m) add(2*tot+num[i][j],tot+num[i][j+1],INF,1); if (i>1 && j>1) add(2*tot+num[i][j],tot+num[i-1][j-1],INF,1); if (i<n && j<m) add(2*tot+num[i][j],tot+num[i+1][j+1],INF,1); if (i>1 && j<m) add(2*tot+num[i][j],tot+num[i-1][j+1],INF,1); if (i<n && j>1) add(2*tot+num[i][j],tot+num[i+1][j-1],INF,1); } if (b1==b2){ while(spfa()) mcf(); if (flow!=b1) ans=-1; }else ans=-1; printf("%d\n",ans); } }G1; int main(){ #ifndef ONLINE_JUDGE freopen("input.txt","r",stdin); // freopen("2668.out","w",stdout); #endif G1.init(); return 0; }
View Code
相关文章推荐
- [BZOJ2668][CQOI2012]交换棋子(费用流)
- 【bzoj2668】[cqoi2012]交换棋子 费用流
- BZOJ 2668 CQOI 2012 交换棋子 费用流
- BZOJ2668: [cqoi2012]交换棋子
- 【BZOJ2668】[cqoi2012]交换棋子 费用流
- 【bzoj2668】【cqoi2012】【交换棋子】【费用流】
- [CQOI2012][bzoj2668] 交换棋子 [费用流]
- BZOJ2668 [cqoi2012]交换棋子 【费用流】
- BZOJ 2668: [cqoi2012]交换棋子(费用流)
- bzoj2668 [cqoi2012]交换棋子
- bzoj 2668: [cqoi2012]交换棋子
- BZOJ 2668: [cqoi2012]交换棋子
- bzoj2668 [cqoi2012]交换棋子
- 【bzoj 2668】: [cqoi2012]交换棋子
- BZOJ 2668 [cqoi2012]交换棋子 | 最小费用最大流
- 【BZOJ2668】【cqoi2012】交换棋子 费用流
- bzoj2668 [cqoi2012]交换棋子(费用流)
- [bzoj2668] [cqoi2012]交换棋子
- [BZOJ2668][CQOI2012]交换棋子
- 2668: [cqoi2012]交换棋子