UVA 1515 Pool construction(最小割)
来源:互联网 发布:妖姬葵 知乎 编辑:程序博客网 时间:2024/05/20 14:44
题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4261
思路:要将草与洞分割开且花费最少,联想到最小割模型。将每一种方案表示为一种割,则答案即为最小割。
建图:首先把边界全部变为草并累积费用。设一源点s,一汇点t,将s与所有草连边(所有非边界草容量为D,代表将其分到洞集合所花费用;所有边界草容量为INF,代表边界草不可转化);将所有洞与t连边,容量为F,代表将其分到草集合所花费用。对于设置围栏:若将所有草与相邻洞连边,容量为B,代表将其隔开所花费用,但这样连边由于草可转化为洞,洞可转化为草,转化后围栏修建无法相应改变(若转化后相邻相同则不需建围栏,而当前图中仍表示修建围栏)。所以,将每个相邻格子连边,容量为B,代表草(洞)与洞(草)分隔所需费用,例如当将草i转化为洞时,仅当s到i的边割开并不能将两个集合分开(存在i到其他草的边),若分开则将i到其他草的边割开(即对应修建围栏),洞转化为草时同理。这样,就将每个方案转化为图中的一个割,最优方案即为图的最小割,由最大流最小割定理,建图后求最大流即可。
#include<cstdio>#include<queue>#include<vector>#include<cstring>#include<iostream>#include<algorithm>#define debuusing namespace std;const int maxn=8000+50;const int INF=0x3f3f3f3f;const int dx[]= {-1,1,0,0};const int dy[]= {0,0,-1,1};struct Edge{ int from,to,cap,flow; Edge(int a=0,int b=0,int c=0,int d=0):from(a),to(b),cap(c),flow(d) {}};struct Dinic{ int n, m, s, t; vector<Edge> edges; vector<int> G[maxn]; bool vis[maxn]; int d[maxn]; int cur[maxn]; void init(int n) { this->n=n; for(int i = 0; i < n; i++) G[i].clear(); edges.clear(); } void addEdge(int from, int to, int cap) { edges.push_back(Edge(from,to,cap,0)); edges.push_back(Edge(to,from,0,0)); int m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BFS() { memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(s); vis[s] = 1; d[s] = 0; while(!Q.empty()) { int x = Q.front(); Q.pop(); for(int i = 0; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(!vis[e.to] && e.cap > e.flow) { vis[e.to] = 1; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vis[t]; } int DFS(int x, int a) { if(x == t || a == 0) return a; int flow = 0, f; for(int& i = cur[x]; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) { e.flow += f; edges[G[x][i]^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow; } int Maxflow(int s, int t) { this->s = s; this->t = t; int flow = 0; while(BFS()) { memset(cur, 0, sizeof(cur)); flow += DFS(s, INF); } return flow; }};Dinic G;int n,m,D,F,B,ans;char st[55][55];inline int isIn(int x,int y){ return x>=1&&x<=n&&y>=1&&y<=m;}inline int ID(int x,int y){ return (x-1)*m+y;}int main(){#ifdef debug freopen("in.in","r",stdin);#endif // debug int t; scanf("%d",&t); while(t--) { ans=0; scanf("%d%d",&m,&n); scanf("%d%d%d",&D,&F,&B); G.init(n*m+2); for(int i=1; i<=n; i++) { getchar(); scanf("%s",st[i]); } for(int i=0; i<m; i++) { ans+=(st[1][i]=='.')?F:0; ans+=(st[n][i]=='.')?F:0; st[1][i]=st[n][i]='#'; } for(int i=1; i<=n; i++) { ans+=(st[i][0]=='.')?F:0; ans+=(st[i][m-1]=='.')?F:0; st[i][0]=st[i][m-1]='#'; } for(int i=1; i<=n; i++) { for(int j=0; j<m; j++) { if(st[i][j]=='.') G.addEdge(ID(i,j+1),n*m+1,F); if(i==1||i==n||j==0||j==m-1) G.addEdge(0,ID(i,j+1),INF); else if(st[i][j]=='#') G.addEdge(0,ID(i,j+1),D); for(int k=0; k<4; k++) { int x=i+dx[k],y=j+dy[k]; if(isIn(x,y+1)) G.addEdge(ID(i,j+1),ID(x,y+1),B); } } } printf("%d\n",ans+G.Maxflow(0,n*m+1)); } return 0;}
0 0
- UVA 1515 Pool construction(最小割)
- uva 1515 Pool construction(最小割)
- 最小割 UVA 1515 Pool construction
- UVA 1515 Pool construction [最小割]
- 1515 - Pool construction(最大流最小割模型)
- [最小割最大流]UVa1515 - Pool construction
- Uva-1515-Pool construction
- UVa 1515 Pool construction
- UVA 1515 Pool construction
- UVA 1515Pool construction
- UVA 1515 Pool construction
- uva 1515 Pool construction(最大流)
- UVA 1515 Pool construction(网络流)
- UVA 1515 (最小割)
- 1515 - Pool construction
- 最大流,最小割(水塘,uva 1515)
- UVa 1515 简单最小割模型
- UVA 1212 - Duopoly(最小割)
- matlab实现ICP(3D迭代最近点算法)
- UOJ 74 [UR #6]破解密码
- 数据库系统概论学习笔记(一):基本概念
- HDU - 2066 - 一个人的旅行
- c# 分页打印多行文本
- UVA 1515 Pool construction(最小割)
- 洛谷 1303——A*B Problem
- 一级路由器静态路由访问二级路由器的方法二
- 【PAT】1091. Acute Stroke
- Linux玩家的福音
- 回顾Activity的启动模式及其应用场景
- 500. Keyboard Row
- 软件架构的概念
- Android自动发送短信