洛谷P3159 [CQOI2012]交换棋子

Posted white_hat_hacker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P3159 [CQOI2012]交换棋子相关的知识,希望对你有一定的参考价值。

巧妙的拆点方式,首先把1看成黑点,0看成空的,几次交换就可以看成一条路径

1)从容量上看,这条路径为1-2-2-2-2-2-……-2-1

2)从费用上看,这条路径每条边费用都是1

于是用一种巧妙的拆点方式,把一个点拆成三个,连两条边,成为一条链,

然后如果是黑点的话就由s向中间那个点连边,如果是路过的话就由一条链的尾部向另一条链的首部连边

这样就满足了上面的条件1)2)

容量的话如果是黑点出来就是(c+1)/2,进来是c/2,其他的以此类推

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 #include<queue>
  7 #define rint register int
  8 #define ll long long
  9 #define MAXN 2000+10
 10 #define pb push_back
 11 #define INF 0x7f7f7f7f
 12 #define oo 0x7f7f7f7f7f7f7f7f
 13 #define pil pair<int,ll>
 14 #define mp make_pair
 15 using namespace std;
 16 int read(){
 17     int x=0,f=1;char ch=getchar();
 18     while(ch<0||ch>9){if(-==ch)f=-1;ch=getchar();}
 19     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
 20     return x*f;
 21 }
 22 struct E{
 23     int from,to,cap,flow;
 24     ll cost;
 25     E(int x=0,int y=0,int c=0,int f=0,ll w=0LL){
 26         from=x,to=y,cap=c,flow=f,cost=w;
 27     }
 28 };
 29 struct Dinic{
 30     int n,m,s,t;
 31     vector<E> es;
 32     vector<int> G[MAXN];
 33     void init(int n,int s,int t){
 34         this->n=n;
 35         this->s=s,this->t=t;
 36         es.clear();
 37         for(int i=0;i<=n;i++)G[i].clear();
 38     }
 39     void add(int x,int y,int cap,ll cost){
 40         es.pb(E(x,y,cap,0,cost));
 41         es.pb(E(y,x,0,0,-cost));
 42         m=es.size();
 43         G[x].pb(m-2),G[y].pb(m-1);
 44     }
 45     int p[MAXN],a[MAXN];
 46     ll d[MAXN];
 47     int b[MAXN];
 48     bool SPFA(int &flow,ll &cost){
 49         p[s]=0,a[s]=INF;
 50         memset(d,0x7f,sizeof(d));
 51         d[s]=0;
 52         memset(b,0,sizeof(b));
 53         b[s]=1;
 54         queue<int> q;
 55         q.push(s);
 56         while(!q.empty()){
 57             int x=q.front();q.pop();b[x]=0;
 58             for(rint i=0;i<G[x].size();i++){
 59                 E &e=es[G[x][i]];
 60                 if(e.cap>e.flow&&d[e.to]>d[x]+e.cost){
 61                     p[e.to]=G[x][i];
 62                     a[e.to]=min(a[x],e.cap-e.flow);
 63                     d[e.to]=d[x]+e.cost;
 64                     if(!b[e.to]){
 65                         b[e.to]=1;
 66                         q.push(e.to);
 67                     }
 68                 }
 69             }
 70         }
 71         if(oo==d[t]){
 72             return 0;
 73         }
 74         flow+=a[t];
 75         cost+=a[t]*d[t];
 76         for(rint i=t;i!=s;i=es[p[i]].from){
 77             es[p[i]].flow+=a[t];
 78             es[p[i]^1].flow-=a[t];
 79         }
 80         return 1;
 81     }
 82     pil MaxfMinc(){
 83         int flow=0;
 84         ll cost=0LL;
 85         while(SPFA(flow,cost));
 86         return mp(flow,cost);
 87     }
 88 }D;
 89 int n,m,s=0,t=MAXN-1;
 90 int id[3][25][25];
 91 int a[25][25],b[25][25],p[25][25];
 92 int cnt1=0,cnt2=0;
 93 void init(){
 94     n=read();m=read();
 95     D.init(t,s,t);
 96     char c[25];
 97     for(rint i=1;i<=n;i++){
 98         for(rint j=1;j<=m;j++){
 99             id[0][i][j]=(i-1)*m+j;
100         }
101     }
102     for(rint k=1;k<=2;k++){
103         for(rint i=1;i<=n;i++){
104             for(rint j=1;j<=m;j++){
105                 id[k][i][j]=id[k-1][i][j]+n*m;
106             }
107         }
108     }
109     for(rint i=1;i<=n;i++){
110         scanf("%s",c+1);
111         for(rint j=1;j<=m;j++){
112             a[i][j]=c[j]-0;
113         }
114     }
115     for(rint i=1;i<=n;i++){
116         scanf("%s",c+1);
117         for(rint j=1;j<=m;j++){
118             b[i][j]=c[j]-0;
119         }
120     }
121     for(rint i=1;i<=n;i++){
122         for(rint j=1;j<=m;j++){
123             if(a[i][j]&&b[i][j]){
124                 a[i][j]=b[i][j]=0;
125             }    
126             else if(a[i][j]){
127                 cnt1++;
128             }
129             else if(b[i][j]){
130                 cnt2++;
131             }
132         }
133     }
134     for(rint i=1;i<=n;i++){
135         scanf("%s",c+1);
136         for(rint j=1;j<=m;j++){
137             p[i][j]=c[j]-0;
138         }
139     }
140 }
141 void add(int x,int y,int c1,int c2){
142     D.add(id[0][x][y],id[1][x][y],c1,0);
143     D.add(id[1][x][y],id[2][x][y],c2,0);
144 }
145 void solve(){
146     int dx[8]={0,0,-1,1,-1,-1,1,1};
147     int dy[8]={1,-1,0,0,-1,1,-1,1};
148     for(rint i=1;i<=n;i++){
149         for(rint j=1;j<=m;j++){
150             if(a[i][j]){
151                 add(i,j,p[i][j]>>1,(p[i][j]+1)>>1);
152                 D.add(s,id[1][i][j],1,0);
153             }
154             else if(b[i][j]){
155                 add(i,j,(p[i][j]+1)>>1,p[i][j]>>1);
156                 D.add(id[1][i][j],t,1,0);
157             }
158             else{
159                 add(i,j,(p[i][j]+1)>>1,p[i][j]>>1);                
160             }
161             for(rint k=0;k<8;k++){
162                 int x=i+dx[k],y=j+dy[k];
163                 if(1<=x&&x<=n&&1<=y&&y<=m){
164                     D.add(id[2][i][j],id[0][x][y],INF,1);
165                 }
166             }
167         }
168     }
169     pil ans=D.MaxfMinc();
170     if(ans.first!=cnt1||cnt1!=cnt2){
171         printf("-1\n");
172     }
173     else{
174         printf("%d\n",ans.second);
175     }
176 }
177 int main()
178 {
179     init();
180     solve();
181     return 0;
182 }

 

以上是关于洛谷P3159 [CQOI2012]交换棋子的主要内容,如果未能解决你的问题,请参考以下文章

p3159 [CQOI2012]交换棋子

[BZOJ2668][CQOI2012]交换棋子

[CQOI2012]交换棋子(最小费用最大流)

bzoj2668 [cqoi2012]交换棋子

题解CQOI2012交换棋子

BZOJ 2668 [cqoi2012]交换棋子 | 最小费用最大流