洛谷 P3405 [USACO16DEC]Cities and States S

新人第一次写博客,打算在这里写一下自己对题目的理解等等,也算是一个记录把

上题

P3405 [USACO16DEC]Cities and States S

题目描述

To keep his cows intellectually stimulated, Farmer John has placed a large map of the USA on the wall of his barn. Since the cows spend many hours in the barn staring at this map, they start to notice several curious patterns. For example, the cities of Flint, MI and Miami, FL share a very special relationship: the first two letters of "Flint" give the state code ("FL") for Miami, and the first two letters of "Miami" give the state code ("MI") for Flint.

Let us say that two cities are a "special pair" if they satisfy this property and come from different states. The cows are wondering how many special pairs of cities exist. Please help them solve this amusing geographical puzzle!

为了训练奶牛们的智力,Farmer John 在谷仓的墙上放了一张美国地图。由于奶牛在谷仓里花了很多时间看这张地图,他们开始注意到一些奇怪的关系。例如,Flint 的前两个字母就是 Miami 所在的 FL 州,Miami 的前两个字母则是 Flint 所在的 MI 州。
确切地说,对于两个城市,它们的前两个字母互为对方所在州的名称。

我们称两个城市是一个一对“特殊的”城市,如果他们具有上面的特性,并且来自不同的省。奶牛想知道有多少对“特殊的”城市存在。请帮助他们解决这个有趣的地理难题!

输入格式

The first line of input contains NN (1 \leq N \leq 200,0001≤N≤200,000), the number ofcities on the map.

The next NN lines each contain two strings: the name of a city (a string of at least 2 and at most 10 uppercase letters), and its two-letter state code (a string of 2 uppercase letters). Note that the state code may be something like ZQ, which is not an actual USA state. Multiple cities with the same name can exist, but they will be in different states.

第一行一个正整数 NN,表示地图上的城市的个数。
接下来 NN 行,每行两个字符串,分别表示一个城市的名称(2 \sim 102∼10个大写字母)和所在州的代码(22 个大写字母)。可能出现类似 ZQ 的州代码,即并不真的是美国的一个州的代码。同一个州内不会有两个同名的城市。

输出格式

Please output the number of special pairs of cities.

输出特殊的城市对数。

输入输出样例

输入 #1复制

6
MIAMI FL
DALLAS TX
FLINT MI
CLEMSON SC
BOSTON MA
ORLANDO FL

输出 #1复制

1

解说:

前置知识:

本题我一开始的想法是用矩阵,但是数据量太大了。

于是用到了我们接下来的主角:BKDR_HASH(字符串哈希)

简单来讲,就是将所给字符串看成一个独特的进制,例如字符串只有大写字母的话可以看成一个31进制的数,将其化为十进制就得到了它的哈希值。

至于为什么是31呢,因为31是一个质数,而在非质数的情况下,会出现哈希冲突的情况(即两个元素对应同一个哈希值)。

具体的BKDR_HASH等我有时间会专门写一篇博客来讲

接下来回到我们的题目:

既然知道了方法,那么接下来就简单了。

首先,我们将所得的所有城市(city)和洲(state)进行转化为[0]*31+[1]的哈希值,再代入到对应的数组的位置上。

接下来,我们用一个大小为1000*1000的矩阵作为哈希数组,对于每一个求出的city和state的哈希值,我们使其对应的 [state][city] 加一,相当于对应的配对中多了一个城市。

然后,再遍历原数组,通过读取 [city][state] 中的数,可知在 city 前两个字母对应的洲下,有 [city][state] 这么多个城市与其匹配,将其累加再除以2(因为两对城市互相匹配,就相当于图的度一样)即可得出配对数。

代码如下:

#include <iostream>

using std::cin;
using std::cout;

using ull = unsigned long long;
const ull prime = 31;

class Solution
{
public:
	int hash[1000][1000];
	int state[200010];
	int city[200010];
	int capital[100];

};

Solution S;

int main()
{
	int n;
	std::cin >> n;
	
	int counter = 0;
	for (int i = 'A'; i <= 'Z'; i++)
	{
		S.capital[i] = ++counter;
	}

	for (int i = 0; i < n; i++)
	{
		char city[11];
		char state[3];
		cin >> city >> state;
		S.city[i] = S.capital[city[0]] * prime + S.capital[city[1]];
		S.state[i] = S.capital[state[0]] * prime + S.capital[state[1]];
		S.hash[S.state[i]][S.city[i]]++;
	}

	counter = 0;
	for (int i = 0; i < n; i++)
	{
		if (S.hash[S.city[i]][S.state[i]] && S.city[i] != S.state[i])
			counter += S.hash[S.city[i]][S.state[i]];
	}

	cout << counter / 2;

	return 0;
}

感谢你的阅读~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值