首页 > 其他分享 >P3057 题解

P3057 题解

时间:2022-08-26 02:04:49浏览次数:198  
标签:cur P3057 题解 短路 int dijkstra color

### 前言
题目传送门

\(\color{red}{see}\space \color{green}{in}\space \color{blue}{my}\space \color{purple}{blog}\)

在学校比赛时遇到了这一题,写一篇题解纪念一下。

本题是最短路好题。

思路

此题明显是最短路。

我们需要求任意两点的最短路的最大值,即全源最短路。

本题共有 \(n^2\) 个点,如果跑 Floyd 时间复杂度是 \(O(n^6)\),非常极限,不是本题正解。

但是,我又不会写 Johnson 全源最短路,怎么办呢?

每个点朝四周建边,容易发现,边的数量不超过 \(4 \times n^2\)。

想到这里,明显可以跑 \(n^2\) 次 dijkstra 实现,因为当边数较小时,跑多次 dijkstra 会比 Floyd 快。

此处 dijkstra 是使用优先队列实现。

那么就很容易写出代码了。

思路总结

  1. 读入数据。

  2. 每个点朝四周建边。

  3. 写一个 dijkstra 的模版。

  4. 统计最大值,输出。

代码

最短路模版没有强制要求,按照自己的习惯写 dijkstra 当然可以。

还有一个小细节:边数 \(m\) 最多有多少?

\(m = 905 * 4 * 2 = 7200\)。

#include <iostream>
#include <cstdio>
#include <queue>
#define N 905
#define M 7205
using namespace std;
int n, nn, A, B;
int dict[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
bool a[35][35];
struct Node
{
	int now, nxt, w;
}e[M];
int head[N], cur;
void add(int x, int y, int k)
{
	e[++cur].now = y;
	e[cur].nxt = head[x];
	e[cur].w = k;
	head[x] = cur;
}
struct Dis
{
	int pos, len;
	bool operator <(const Dis &t) const
	{
		return len > t.len; 
	}
}dis[N];
bool vis[N];
int dijkstra(int first) 
{
	priority_queue <Dis> Q;
	for (int i = 1; i <= nn; i++) dis[i].pos = i, dis[i].len = 2147483647, vis[i] = false;
	dis[first].len = 0;
	Q.push(dis[first]);
	while (!Q.empty())
	{
		int topi = Q.top().pos;
		Q.pop();
		if (vis[topi]) continue;
		vis[topi] = true;
		for (int i = head[topi]; i; i = e[i].nxt)
			if (dis[topi].len + e[i].w < dis[e[i].now].len)
			{
				dis[e[i].now].len = dis[topi].len + e[i].w;
				Q.push(dis[e[i].now]);
			}
	}
    //此处有是惟一与普通模版不同的地方,需要找出最大值。
	int maxn = 0;
	for (int i = 1; i <= nn; i++) maxn = max(maxn, dis[i].len);
	return maxn;
}
void Input()
{
	scanf("%d%d%d", &n, &A, &B);
	nn = n * n;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{
			char x;
			cin >> x;
			if (x == '(') a[i][j] = true;
		}
}
void get_edge()
{
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			for (int k = 0; k < 4; k++)
			{
				int x = i + dict[k][0], y = j + dict[k][1];
				if (!(1 <= x && x <= n && 1 <= y && y <= n)) continue;
				int t1 = n * (i-1) + j, t2 = n * (x-1) + y;
				if (a[i][j] == a[x][y]) add(t1, t2, A);
				else add(t1, t2, B);
			}
}
void solve()
{
	int maxn = 0;
	for (int i = 1; i <= nn; i++) maxn = max(maxn, dijkstra(i));
	printf("%d", maxn);
}
int main()
{
	Input();
	get_edge();
	solve();
	return 0;
}

首发:2022-05-26 13:26:36

标签:cur,P3057,题解,短路,int,dijkstra,color
From: https://www.cnblogs.com/liangbowen/p/16622877.html

相关文章

  • P4944 题解
    前言题目传送门!或许更好的阅读体验?这题算是一道中模拟?码量不会很高,大概只有\(100\)至\(150\)行。思路输入地图。注意,还不能读入蛇的行动指令,因为我们不知道......
  • gdfzoj 比赛题解
    前言本次比赛:初一训练5.21/编号531题目难度中等偏上,有几题比较简单,有两三题较难。T1题目:gdfzoj1441思路:算是一道暴力题。由于\(h_{i,j}\)范围很小,考虑二分答......
  • P8344 题解
    ###前言题目传送门\(\color{red}{see}\space\color{green}{in}\space\color{blue}{my}\space\color{purple}{blog}\)这题作为本次比赛的T1,难度感觉还行,算是一道结......
  • AT2580 题解
    前言题目传送门!更好的阅读体验?这题是常规的二分答案。前置知识:二分答案教大家一个小技巧:如何判断一题是否可以使用二分答案,以及如何编写程序?设计\(f(x)\)函数,确......
  • P8400 题解
    前言题目传送门!或许更好的阅读体验?这题非常简单,考察读入读出,以及较简单的代数运算。思路我们可以利用代数解这道题目。设一共有\(n\)个大盒子,\(m\)个小盒子。得......
  • P1415 题解
    前言题目传送门!更好的阅读体验?这题是一道挺好的\(\texttt{dp}\)题啊,但大家的题解都写得不够详细。所以,我来补一篇\(\LaTeX\)题解,希望能帮助大家。思路首先是读......
  • CF371B 题解
    前言题目传送门!更好的阅读体验?这题显然没有蓝的难度。其他题解代码不好看,而且没有讲清楚,那我补一发吧。题目简述有两个数\(a\),\(b\),每次操作可以给\(a\)或\(b\)......
  • P8410 题解
    前言题目传送门!更好的阅读体验?本次比赛第二题,好像没有人抢题解,那我来一发。思路还是挺巧妙的。\(\texttt{10pts}\)思路深搜求解即可。最坏情况,时间复杂度\(O(n!......
  • CF722B 题解
    前言题目传送门!更好的阅读体验?这是一道简单的字符串练手题。思路每次暴力计数,是否为元音。最后判断是否满足题意即可。重点是字符串读入问题。由于字符串读入部分......
  • AT1330 题解
    前言题目传送门!更好的阅读体验?这一题内部比赛时考到了,个人觉得是一道二分答案好题。本题时间很宽松,导致\(O(n\log^2n)\)的代码可以跑过去。但是,我内部比赛的时限......