UVALive-7303- Aquarium【最小生成树】【连通块】
2016-08-09 22:41
281 查看
UVALive - 7303- Aquarium
题目链接:7303
题目大意:给你一个r * c的格子,每个格子有一个 ‘ \ ’ 或者 ‘/’ 的墙,以及打掉墙的费用,问使得所有块联通的最小费用。(看图好理解)
题目思路:就是将他化成一个图,联通的块相当于一个点,两个点之间有一条边,边的权值为墙的费用。
转化为连通块的思路是:每个格子看成两部分,左侧和右侧。以一行来看,假设两个格子A,B。那么B格子的右侧的编号一定和A格子的左侧的编号相同。如图所示
给每个格子的左右侧标上号,然后加入边,边的两个端点为一个格子的两个编号。权值为墙的费用
然后处理行与行之间的边,稍微讨论一下,假设上边格子为A,下面格子为B。那么如果A是‘/’,B是’/’,那么A的右格子和B的左格子是相通的,这时候加一条边,将权值设为0就可以了。
注意数组大小!!!
以下是代码:
#include <iostream> #include <iomanip> #include <fstream> #include <sstream> #include <cmath> #include <cstdio> #include <cstring> #include <cctype> #include <algorithm> #include <functional> #include <numeric> #include <string> #include <set> #include <map> #include <stack> #include <vector> #include <queue> #include <deque> #include <list> using namespace std; typedef long long ll; string s[105]; int val[105][105]; struct node { int a,b; }g[105][105]; struct node2 { int a,b,len; }edge[40005]; int fa[20005]; int kk; //=======最小生成树==== void add(int u, int v,int w) { edge[kk].a = u; edge[kk].b = v; edge[kk++].len = w; } bool cmp(node2 a,node2 b) { return a.len < b.len; } int getfather(int v) { return (fa[v] == v) ? v : fa[v] = getfather(fa[v]); } void merges(int x,int y) { x = getfather(x); y = getfather(y); if (x != y) fa[x] = y; } //============== int main() { int t; cin >> t; int lllll = 1; while(t--) { int c,r; cin >> c >> r; kk = 0; for (int i = 0; i < c; i++) { cin >> s[i]; } for (int i = 0; i < c; i++) { for (int j = 0; j < r; j++) { cin >> val[i][j]; } } int p = 1; for (int i = 0; i < c; i++) { for (int j = 0; j < r; j++) { if (j == 0) { g[i][j].a = p++; g[i][j].b = p++; add(g[i][j].a,g[i][j].b,val[i][j]); } else { g[i][j].a = g[i][j - 1].b; g[i][j].b = p++; add(g[i][j].a,g[i][j].b,val[i][j]); } if (i != 0) { if (s[i - 1][j] == '/') { if (s[i][j] == '/') { add(g[i][j].a,g[i - 1][j].b,0); } else { add(g[i][j].b,g[i - 1][j].b,0); } } else { if (s[i][j] == '/') { add(g[i][j].a,g[i - 1][j].a,0); } else { add(g[i][j].b,g[i - 1][j].a,0); } } } } } for (int i = 1; i <= 20001; i++) { fa[i] = i; } sort(edge,edge + kk,cmp); int ans = 0; for (int i = 0; i < kk; i++) { int u = edge[i].a; int v = edge[i].b; if (getfather(u) != getfather(v)) { merges(u,v); ans += edge[i].len; } } printf("Case %d: ",lllll++); cout << ans << endl; } }
相关文章推荐
- UVALive 7303 Aquarium 最小生成树
- UVALive-7303 Aquarium (最小生成树)
- UVALive 3662 Another Minimum Spanning Tree 曼哈顿最小生成树
- UVALive 3662 Another Minimum Spanning Tree [离散化+线段树+最小生成树]
- UVALive 6437 Power Plant 【最小生成树 + 思维】
- 曼哈顿最小距离生成树(poj 3241&& UVALive 3662)
- UVALive - 5713 最小生成树
- UVALive 3887 边权极差最小生成树模板
- UVALive - 4872 最小生成树
- UVAlive 3662 Another Minimum Spanning Tree 莫队算法,曼哈顿最小生成树
- UVALive - 7303 Aquarium(最小生成树)
- UVA Live 6437 Power Plant 最小生成树
- 【UVALive】3887 Slim Span 枚举+最小生成树
- UVALive - 4848 Tour Belt(暴力+最小生成树)
- 最小生成树应用uvalive5713
- B - Bus Problem UVALive - 7001 最小生成树
- UVA Live 6437 Power Plant 最小生成树
- UVALive 6837 (最小生成树)
- Another Minimum Spanning Tree - UVaLive 3662 曼哈顿最小生成树
- UVALive 4872 Underground Cables 最小生成树