Codeforces 316C2 题解 (网络流-最小费用最大流)
来源:互联网 发布:unity3d 2d骨骼 编辑:程序博客网 时间:2024/05/16 07:49
题目描述
在一个n*m的网格图里面,每一个cell中有一个shoe,网格中共有n*m/2双鞋子,两个标号相同的鞋子被视为一双。我们视每一只鞋子都和与其配对的鞋子相邻(所在的格子有邻边)的状态为理想状态。题目给出当前状态,要求求出最少需要变化几只鞋子的位置才能达到理想状态。
Sample Input:
3 4
1 3 2 6
2 1 5 6
4 4 5 3
Sample Output:
4
Hint:
对于样例,只需要改变四只鞋子的位置(既图中灰色部分的鞋子)就可以达到理想状态。
题解
这道题的模型并不明显,但是经过对题目性质的分析,我们就可以找到切入点。
贪心地想,为了在最短的步数之内达到理想状态,我们可知解题的两个性质:
- 首先,对于某一只与可配对鞋子不相邻的鞋子,它或它的配对鞋一定是移动或被移动过的。
- 对于每一对可匹配的鞋子,它们不会同时被移动。
那么我们可以考虑,将网格内的点分为两个集合,每个集合内的点都互不相邻。然后从源点向其中一个集合的点连一条流量为1权值为0的边,另一个集合的点向汇点连一条流量为1权值为0的边。对于与源点相连的那个集合的点,向相邻的点连边,可以匹配的连权值为0的边,不可匹配的连权值为1的边。
跑一边最小费用最大流可以得到答案。
代码
套路很深。
#include <cstdio>#include <iostream>#include <queue>#include <cstring>using namespace std;const int maxn=85;const int INF=int(1e9)+7;int n,m;int a[maxn][maxn];void read() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); return;}const int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};const int maxd=maxn*maxn;const int maxe=int(1e5)+10;int tot=0;int head[maxd];int S,T;struct Edge { int from,to,cap,cost,next; Edge() {} Edge(int x,int y,int a,int b,int c):from(x),to(y),cap(a),cost(b),next(c) {}}eage[maxe*2];void add(int x,int y,int a,int b) { eage[tot]=Edge(x,y,a,b,head[x]), head[x]=tot++; eage[tot]=Edge(y,x,0,-b,head[y]), head[y]=tot++; return;}bool used[maxd],vis[maxd];int dis[maxd];queue<int> que;int ans=0;bool spfa() { for(int i=0;i<maxd;i++) used[i]=false,dis[i]=INF,vis[i]=false; while(que.size()) que.pop(); que.push(S); used[S]=true; dis[S]=0; while(que.size()) { int u=que.front(); que.pop(); used[u]=false; for(int i=head[u];~i;i=eage[i].next) if(eage[i].cap && dis[eage[i].to]>dis[u]+eage[i].cost) { int v=eage[i].to; dis[v]=dis[u]+eage[i].cost; if(!used[v]) { used[v]=true; que.push(v); } } } return (dis[T]<INF);}int dfs(int u,int flow) { if(u==T) { ans+=dis[u]*flow; return flow; } vis[u]=true; int ret=0; for(int i=head[u];~i;i=eage[i].next) if(!vis[eage[i].to] && eage[i].cap && dis[eage[i].to]==dis[u]+eage[i].cost) { int v=eage[i].to; int newf=dfs(v,min(flow,eage[i].cap)); eage[i].cap-=newf; eage[i^1].cap+=newf; ret+=newf; flow-=newf; if(!flow) break; } if(!ret) dis[u]=-1; return ret;}int MCMF() { ans=0; while(spfa()) dfs(S,INF); return ans;}void build() { tot=0; memset(head,-1,sizeof head); #define pos(i,j) (S+(i-1)*m+j) S=1,T=pos(n,m)+1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if((i&1)==(j&1)) add(pos(i,j),T,1,0); else { add(S,pos(i,j),1,0); for(int k=0;k<4;k++) { int x=i+dir[k][0],y=j+dir[k][1]; if(x<1 || y<1 || x>n || y>m) continue; add(pos(i,j),pos(x,y),1,(a[i][j]!=a[x][y])); } } } return;}int main() { read(); build(); printf("%d\n",MCMF()); return 0;}
1 0
- Codeforces 316C2 题解 (网络流-最小费用最大流)
- 【HDU3488】【网络流】【最小费用最大流】Tour 题解
- codeforces 277E 最小费用最大流
- 网络最大流和最小费用流
- 网络最大流和最小费用流
- 【最大流+最小费用流】网络扩容
- 网络流 最小费用最大流问题
- 网络流 最小费用最大流
- 网络流-最小费用最大流
- 网络流问题-最小费用最大流
- 网络流-最小费用最大流
- 网络流--最小费用最大流
- 网络流(最大流和最小费用流)
- Going Home(网络流 最小费用最大流)
- bzoj1834: [ZJOI2010]network 网络扩容(最小费用最大流)
- [网络流24题] 17 运输问题(网络费用流量,最小费用最大流)
- 最小费用最大流
- 最小费用最大流
- UE4中切换关卡
- Unity 3D 海水的实现2 折射与反射 离屏相机的渲染
- linux之强大的sed
- 微信分享单独的大图片
- Struts2总结---拦截器的实现原理及源码剖析 (6)
- Codeforces 316C2 题解 (网络流-最小费用最大流)
- 网络安全学习资料总汇
- 看开源代码利器—用Graphviz + CodeViz生成C/C++函数调用图(call graph)
- js数据类型: 对象,数组,等
- java的守护线程与非守护线程
- iOS学习笔记之-UIScrollView
- 嵌入式项目1--UCOSiii操作系统的学习
- Android 属性动画ValueAnimator和ObjectAnimator的高级用法
- java对生成的Excl进行加密