【wikioi】1002 搭桥(dfs+最小生成树)
http://wikioi.com/problem/1002/
今天开始又开始刷水了哈T_T。照着hzwer神犇的刷题记录刷!!!
题解:
一开始我也不会,但是我想到了直接爆搜T_T。
好吧,题解。
首先对于第一个问,我们直接深搜就行了,沿着相连的城市走(ps,这里很坑啊啊啊,左上角和右上角还有左下角右下角也算联通啊!!!一开始我没发现!!)
那么我们就可以将这些城市看做缩点后的点集x。
然后我们再爆搜,依次从每个'#'点出发,向四个方向拓展(准确的说是四个方向,每个方向有3行(列)!!),将点集x中不同的点连边,在这里有个剪枝,如果拓展某个方向时,遇到了和自己点集一样的点,那么可以直接停止拓展。理由太简单了,自己想。
然后连完边后直接跑个最小生成树。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getnum()
#define print(a) printf("%d", a)
#define dbg(x) cout << #x << " = " << x << endl
inline int getnum() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; }
const int N=60;
const int dx[8]={0,0,1,1,1,-1,-1,-1}, dy[8]={1,-1,0,1,-1,0,1,-1};
struct ED { int x, y, w; }e[N*N*N];
int n, m, a[N][N], d[N][N], ans, sum, cnt, p[N*N];
inline const bool cmp(const ED &a, const ED &b) { return a.w<b.w; }
const int ifind(const int &x) { return x==p[x]?x:p[x]=ifind(p[x]); } void dfs1(const int &x, const int &y) {
int fx, fy;
d[x][y]=ans;
rep(i, 8) {
fx=x+dx[i]; fy=y+dy[i];
if(fx<1 || fx>n || fy<1 || fy>m || d[fx][fy] || !a[fx][fy]) continue;
dfs1(fx, fy);
}
}
void work1() {
for1(i, 1, n) for1(j, 1, m) if(a[i][j] && !d[i][j]) { ++ans; dfs1(i, j); }
printf("%d\n", ans);
}
inline const bool insert(const int &fx, const int &fy, const int &x, const int &y, const int &w) {
if(x<1 || x>n || y<1 || y>m || !d[x][y]) return 1;
if(d[x][y]==d[fx][fy]) return 0;
e[++cnt].x=d[fx][fy]; e[cnt].y=d[x][y];
e[cnt].w=w-1;
return 1;
}
void build(const int &x, const int &y) {
for1(i, x+1, n) if(!insert(x, y, i, y, i-x) || !insert(x, y, i, y+1, i-x) || !insert(x, y, i, y-1, i-x)) break;
for3(i, x-1, 1) if(!insert(x, y, i, y, x-i) || !insert(x, y, i, y+1, x-i) || !insert(x, y, i, y-1, x-i)) break;
for1(i, y+1, m) if(!insert(x, y, x, i, i-y) || !insert(x, y, x+1, i, i-y) || !insert(x, y, x-1, i, i-y)) break;
for3(i, y-1, 1) if(!insert(x, y, x, i, y-i) || !insert(x, y, x+1, i, y-i) || !insert(x, y, x-1, i, y-i)) break;
}
void work2() {
for1(i, 1, n) for1(j, 1, m) if(a[i][j]) build(i, j);
sort(e+1, e+1+cnt, cmp);
for1(i, 1, ans) p[i]=i;
sum=ans=0; int fx, fy;
for1(i, 1, cnt) {
fx=ifind(e[i].x); fy=ifind(e[i].y);
if(fx!=fy) {
p[fx]=fy;
++ans;
sum+=e[i].w;
}
}
printf("%d %d\n", ans, sum);
} int main() {
read(n); read(m); char c;
for1(i, 1, n) for1(j, 1, m) {
for(c=getchar(); c!='#'&&c!='.'; c=getchar());
if(c=='#') a[i][j]=1;
}
work1();
work2();
return 0;
}
题目描述 Description
有一矩形区域的城市中建筑了若干建筑物,如果某两个单元格有一个点相联系,则它们属于同一座建筑物。现在想在这些建筑物之间搭建一些桥梁, 其中桥梁只能沿着矩形的方格的边沿搭建,如下图城市1有5栋建筑物,可以搭建4座桥将建筑物联系起来。城市2有两座建筑物,但不能搭建桥梁将它们连接。城 市3只有一座建筑物,城市4有3座建筑物,可以搭建一座桥梁联系两栋建筑物,但不能与第三座建筑物联系在一起。
输入描述 Input Description
在输入的数据中的第一行包含描述城市的两个整数r 和c, 分别代表从北到南、从东到西的城市大小(1 <= r <= 50 and 1 <= c<= 50). 接下来的r 行, 每一行由c 个(“#”)和(“.”)组成的字符. 每一个字符表示一个单元格。“#”表示建筑物,“.”表示空地。
输出描述 Output Description
在输出的数据中有两行,第一行表示建筑物的数目。第二行输出桥的数目和所有桥的总长度。
样例输入 Sample Input
样例1
3 5
#...#
..#..
#...#
样例2
3 5
##...
.....
....#
样例3
3 5
#.###
#.#.#
###.#
样例4:
3 5
#.#..
.....
....#
样例输出 Sample Output
样例1
5
4 4
样例2
2
0 0
样例3
1
0 0
样例4
3
1 1
数据范围及提示 Data Size & Hint
见描述
【wikioi】1002 搭桥(dfs+最小生成树)的更多相关文章
- 搭桥|codevs1002|最小生成树|Prim|并查集|Elena
1002 搭桥 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 有一矩形区域的城市中建筑了若干建筑物,如果某两个单元格有一个点 ...
- codevs 1002 搭桥
codevs 第一道题 先贴描述 1002 搭桥 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description ...
- Code VS 1002 搭桥
题目描述 Description 有一矩形区域的城市中建筑了若干建筑物,如果某两个单元格有一个点相联系,则它们属于同一座建筑物.现在想在这些建筑物之间搭建一些桥梁,其中桥梁只能沿着矩形的方格的边沿搭建 ...
- [wikioi 1519]过路费(最小生成树+树链剖分)
题目:http://www.wikioi.com/problem/1519/ 题意:给你一个连通的无向图,每条边都有权值,给你若干个询问(x,y),要输出从x到y的路径上边的最大值的最小值 分析:首先 ...
- wikioi 1002 旁路
意甲冠军:这个问题刚开始的问题,有错误的含义,原桥始建于一条直线.无论多么遥远. 思维:dfs寻求答案的第一个问题.然后做最小生成树,双方不能大桥将设置INF即可了.然后假设用到INF的边就加上0即可 ...
- 图的全部实现(邻接矩阵 邻接表 BFS DFS 最小生成树 最短路径等)
1 /** 2 * C: Dijkstra算法获取最短路径(邻接矩阵) 3 * 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> ...
- ZOJ Problem Set - 1002(DFS)
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1002 题意:给出一个n,有n*n大小的城市,(.)表示空地,从碉堡(O)射 ...
- HDU_6016_(Bestcoder round #92 1002)_(dfs)(暴力)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6016 题意:给定男羊和女羊的朋友关系,即给定一个图,问从任意一只羊开始连续数四只不相同的羊的方法数. ...
- 洛谷1002 容斥原理+dfs OR DP
//By SiriusRen #include <bits/stdc++.h> using namespace std; #define int long long ,,,,-,-,-,- ...
随机推荐
- poj1182(食物链)续
意 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用 ...
- MyBatis调用存储过程
MySQL存储过程 DROP PROCEDURE IF EXISTS transferMoney; -- 实现转账功能的存储过程 CREATE PROCEDURE transferMoney ( IN ...
- 在 FREEBUF 投放广告
在 FREEBUF 投放广告 FreebuF黑客与极客—高质量的全球互联网安全媒体,同时也是爱好者们交流.分享安全技术的最佳平台.本站读者群以IT.政企信息安全人员.互联网安全爱好者和学生为主,对互联 ...
- Python中请使用isinstance()判断变量类型
一.isinstance() 在Python中可以使用type()与isinstance()这两个函数判断对象类型,而isinstance()函数的使用上比type更加方便. # coding=utf ...
- RadioButtonList单选和RequiredFieldValidator验证是否选中
<asp:RadioButtonList ID="Radio2" RepeatDirection="Horizontal" runat="ser ...
- volatile关键字
[本文链接] http://www.cnblogs.com/hellogiser/p/volatile.html [分析] volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编 ...
- 1.10 编程之美-双线程下载[double threads to download]
[本文链接] http://www.cnblogs.com/hellogiser/p/double-threads-to-download-and-write.html [题目] 网络上下载数据,然后 ...
- 六间房PK同时观看两方视频(绕过VIP限制)+直播状态批量监测
可交换两个视频位置,记住最后播放记录,游客VIP限制也能观看视频等功能. 使用方法: 1.先运行 6.cn.live.exe 分别打开两个主播房间的网页(VIP限制也能获取视频的文件名) (房间已满提 ...
- 【python-mysql】在ubuntu下安装python-mysql环境
1.先安装mysql sudo apt-get install mysql-server apt-get isntall mysql-client sudo apt-get install libmy ...
- HDU 1521 排列组合 指数型母函数
排列组合 Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u Submit Status D ...