H - Aquarium (UVALive - 7303 )

- 题目大意

给你一个r * c的格子,每个格子有一个 ‘ \ ’ 或者 ‘/’ 的墙,以及打掉墙的费用,问使得所有块联通的最小费用。(自己可以配合图来看好理解一点)

- 解题思路

我们可以将其转化成联通块的问题,就是把每个格子看成两部分,左侧和右侧。以一行来看,假设两个格子A,B。那么B格子的右侧的编号一定和A格子的左侧的编号相同。给每个格子的左右侧标上号,然后加入边,边的两个端点为一个格子的两个编号。权值为墙的费用然后处理行与行之间的边,然后假设上边格子为A,下面格子为B。那么如果A是‘/’,B是’/’,那么A的右格子和B的左格子是相通的,这时候加一条边,将权值设为0就可以了。(注意位置和数组大小!!!)

- 代码

#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<string>
using namespace std;
const int MAX = 1e6;
int fa[MAX];
string str[400];
int num[150][150];
int sum,sum1,cnt;
void init()
{
	for (int i = 1; i <= MAX; i++)
	{
		fa[i] = i;
	}
	cnt=0;
}

struct Edge {
	int u, v, w;
	bool operator<(const Edge &rhs)const {
		return w < rhs.w;
	}
}e[MAX];

struct Edge2{
       int u,v;

}maps[150][150];
void addEdge(int u,int v,int w)
{
    e[cnt].v=v;
    e[cnt].u=u;
    e[cnt++].w=w;
}
int find(int x)
{
	if (x == fa[x])
		return x;
	else
		return fa[x] = find(fa[x]);
}

bool Union(int x, int y)
{
	int fx = find(x), fy = find(y);
	if (fx == fy)
		return false;
	fa[fx] = fy;
	return true;
}

void kruskal(int m)
{
	sort(e, e + m);
		for (int i = 0; i < m; i++)
		{
			int u = e[i].u, v = e[i].v, w = e[i].w;
			if (Union(u, v))
			{
				sum +=w;
		}
	}
}

int main()
{
	int t,n, m;
	scanf("%d",&t);
for(int q=1;q<=t;q++)
{
    scanf("%d%d",&n,&m);
    init();
    for(int i=0;i<n;i++)
    {
    cin>>str[i];
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
        scanf("%d",&num[i][j]);
        }
    }
		int p = 1;
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
			{
				if (j == 0)
				{
					maps[i][j].u = p++;
					maps[i][j].v = p++;
					addEdge(maps[i][j].u, maps[i][j].v, num[i][j]);
				}
				else
				{
					maps[i][j].u = maps[i][j - 1].v;
					maps[i][j].v = p++;
					addEdge(maps[i][j].u, maps[i][j].v, num[i][j]);
				}
				if (i != 0)
				{
					if (str[i - 1][j] == ‘/‘)
					{
						if (str[i][j] == ‘/‘)
						{
							addEdge(maps[i][j].u, maps[i - 1][j].v, 0);
						}
						else
						{
							addEdge(maps[i][j].v, maps[i - 1][j].v, 0);
						}
					}
					else
					{
						if (str[i][j] == ‘/‘)
						{
							addEdge(maps[i][j].u, maps[i - 1][j].u, 0);
						}
						else
						{
							addEdge(maps[i][j].v, maps[i - 1][j].u, 0);
						}
					}
				}
			}
		}
		sum=0;
		kruskal(cnt);
		printf("Case %d: %d\n",q,sum);
}
	return 0;
}

  

原文地址:https://www.cnblogs.com/alpacadh/p/8449455.html

时间: 2024-10-09 17:16:07

H - Aquarium (UVALive - 7303 )的相关文章

H.264(MPEG-4 AVC)级别(Level)、DPB 与 MaxDpbMbs 详解(转载)

转自:http://www.cnblogs.com/zyl910/archive/2011/12/08/h264_level.html 对于H.264(MPEG-4 AVC)而言,级别(Level)是与档次(Profile)同等重要的参数.但很多文章说的很简略,只是说标清视频一般用3.1,高清用4,具体含义语焉不详.于是我做了一番研究. 一.级别详表 级别(Level)是用来约束 分辨率.帧率 和 码率 的.详细信息请看表格—— Level Max macroblocks Max video b

China-老IT人编的笑话,未成年人勿进,R级之上,越过A级,属于‘H’级(Hack除外)

    按:本来不想讲过头的笑话,但弟兄们觉得我太严肃(之一就是不会说笑),学生们觉得我太严厉,想想也是,高中听女英语老师讲"洗Zao"的笑话,很受用,就讲两个吧. 笑话1:本人认为最N$(After 'A' && Before 'C')的单词是Ethernet,从前以为Earth是土做的,实际上含有大量 E(Electronic),以为人是Human,但是加电("E")之后才之后发现是He' 'u' 'man,以为西方He竖起中指太...,没想到W

Repeated Substrings(UVAlive 6869)

题意:求出现过两次以上的不同子串有多少种. /* 用后缀数组求出height[]数组,然后扫一遍, 发现height[i]-height[i-1]>=0,就ans+=height[i]-height[i-1]. */ #include<cstdio> #include<iostream> #include<cstring> #define N 100010 using namespace std; int sa[N],rk[N],ht[N],t1[N],t2[N]

F - Elevator Stopping Plan (UVALive - 2949)

- 题目大意 某个公司只有一个电梯, 现在有n 个人从1楼, 他们有各自想要到达的楼层, 然后电梯每上一楼需要4 秒, 每在一个楼层开门需要10 秒, 然后然爬楼梯的话需要20一楼.问, 如何用最短的时间让所有人都到达各自想要到的楼层. - 解题思路 因为人可以爬楼梯, 所以可以在某个楼层下楼之后走楼梯到达想要到的楼层, 只要在最后一个人到达之前就可以. 对于时间可以采取二分的方式搜索, 所以只要判断某个时间能否将所有人送到指定楼层就可以了. 对于判断我们可以用贪心去做, 尽量让电梯停在较高的楼

A - X-Plosives (UVALive - 3644)

- 题目大意 有若干个由两种元素组成的简单化合物,现在把它们装进车里,如果车上有恰好有k种简单化合物并且恰好有k种元素的话,那么就会引发爆炸,所以车上的化合物必须避免满足这个条件. - 解题思路 如果元素表示点,那么化合物就表示边,要爆炸的条件就是形成环,即为k个点k条边,那么就肯定存在环.直接用并查集判断就好了. - 代码 #include<iostream> #include<cstdio> using namespace std; const int MAX = 1e5 +

散列表的数学分析(精解)--通过链表法解决碰撞

散列表的具体实现就不多做介绍了,就是一个数组,每个下标存储的是碰撞的元素的链表头指针,如下图所示: 下面直接研究对用链接法散列的分析: 给定一个能存放n个元素的.具有m个槽位的散列表T,定义T的装载因子α为n/m,即一个链中平均存储的元素数. 用链接法散列的最坏情况性能很差:所有的n个关键字都散列到同一个槽中,从而产生出一个长度为n的链表.这时,最坏情况下查找的时间为O(n),再加上计算散列函数的时间,这么一来就和用一个链表来链接所有的元素差不多了.显然我们并不是因为散列表的最坏情况性能差才用它

《Windows服务器配置与管理》模块化教学任务工单(No.5)

工作任务描述 在上一个项目中,HT公司为HW的部署windows server 2008 以后,又添置了3块8G的(实验模拟)硬盘,要求完成以下操作 项目要求: 1. 将这3块磁盘升级为动态磁盘. 2. 在磁盘1上创建一个简单卷,大小为10M,格式化为NTFS,卷标为E: 3. 完成后,扩展E卷,由磁盘1和磁盘2各提供10M,最后E卷的大小为多少M? 4. 在磁盘2和磁盘3上划出15M出来做镜像卷,设置卷标为F: 5. 在磁盘2和磁盘3上划出20M出来做带区卷,设置卷标为G: 6. 在磁盘1,磁

windows下开发PHP扩展(无需Cygwin)

第一步:准备 1.php源码包和windows下的二进制包,以及安装Visual C++,并把Microsoft Visual Studio/Common/MSDev98/Bin的绝对路径添加到windows环境变量 2.解压源码包到d:/php_src 3.进入d:/php_src/ext目录,复制skeleton文件夹,并重命名为要开发扩展的名字,本例为“linvo” 4.把二进制包中dev目录下的php5ts.lib文件,拷入新建的linvo目录 5.编辑linvo目录中的php_skel

UVALive - 3641 Leonardo&#39;s Notebook(polya计数)

题意:给出26个大写字母的置换B,问是否存在一个置换A,使A*A=B? 两个长度为N的相同循环相乘,当N为奇数时结果也是一个长度为N的循环,当N为偶数时分裂为两个长度为N/2的循环.相反,对于一个任意长度为N的奇数循环B,都能找到一个长度为N的循环A使得A*A=B,对于任意两个长度为N(N不一定为偶数)的不相交循环B和C,都能找到一个长度为2N的循环A使得A*A=B*C. 于是只要判断置换B里循环长度相同的且都为偶数(2,4,6, 8.....)的循环个数是不是都为偶数(偶数就能两两配对),只要