【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 ,,,,-,-,-,- ...
随机推荐
- 学习jquery mobile
学习jquery mobile的时间不是很长,在学习的过程当中也遇到了很多令人抓狂的问题,在网上搜索问题答案的时候发现,现在关于jquery mobile的文章还不是很多,所以,我也是一边学习,一边摸 ...
- bash read命令用法
read -p "Enter your student ID: " USERNAMEread -s -p "Enter your password: " PAS ...
- Cocos2d 学习资料推荐
总算找到了一本介绍cocos2d的好书,注意,不是cocos2d-x!这本书叫 <cocos2d 权威指南> 定价99元,淘宝60多元,详细介绍了cocos2d的各个方面!不过你需要有oc ...
- php中GD库的简单使用
在php中需要图像处理的地方GD库会发挥重要的作用,php可以创建并处理包括GIF,PNG,JPEG,WBMP以及XPM在内的多种图像格式,简单的举几个例子: 1.用GD库会创建一块空白图片,然后绘制 ...
- Enum:Smallest Difference(POJ 2718)
最小的差别 题目大意:输入一串数字,问你数字的组合方式,你可以随意用这些数字组合(无重复)来组合成一些整数(第一位不能为0),然后问你组合出来的整数的差最小是多少? 这一题可以用枚举的方法去做,这里我 ...
- java将白色背景图片转换成无色
package com.cxf.dao; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.Buffer ...
- UVA11806-Cheerleaders(容斥原理+二进制)
In most professional sporting events, cheerleaders play a major role in entertaining the spectators. ...
- WebStorm设置字体和颜色
新建Scheme + 修改字体 ctrl+alt+s打开Settings界面,Editor > Colors&Fonts > Font. Default scheme是亮色调,但我 ...
- FreeMarker备忘
以下内容全部是网上收集: FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成: ,文本:直接输出的部分 ,注释:<#-- ... --& ...
- The Unique MST(poj 1679)
题意:求次小生成树,若权值和与最小生成树相等,输出"Not Unique!" :否则,输出mst /* 次小生成树 首先明白一点,次小生成树是由最小生成树改变一条边得来的,然后我们 ...
