1 条题解

  • 0
    @ 2025-8-24 21:44:50

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar liangbowen
    不能再摆了,,,

    搬运于2025-08-24 21:44:50,当前版本为作者最后更新于2022-05-26 13:26:36,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    前言

    题目传送门

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

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

    本题是最短路好题。

    思路

    此题明显是最短路。

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

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

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

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

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

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

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

    思路总结

    1. 读入数据。

    2. 每个点朝四周建边。

    3. 写一个 dijkstra 的模版。

    4. 统计最大值,输出。

    代码

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

    还有一个小细节:边数 mm 最多有多少?

    m=90542=7200m = 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;
    }
    
    • 1

    信息

    ID
    2121
    时间
    1000ms
    内存
    125MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者