首页 > 其他分享 >P8906 [USACO22DEC] Breakdown P 题解

P8906 [USACO22DEC] Breakdown P 题解

时间:2024-09-25 18:23:09浏览次数:7  
标签:Breakdown 0x3f int 题解 P8906 memset le 复杂度

P8906 [USACO22DEC] Breakdown P 题解

显然的套路是删边转化为加边。

考虑到维护整条路径不好维护,于是考虑转化维护 \(f_{i,k},g_{i,k}\) 分别表示 \(1,n\) 到 \(i\) 走了 \(k\) 步时的最短路。那么此时 \(k\le 4\)。

我们先考虑 \(f\) 的转移,\(g\) 的转移是等价的。

那么对于 \((x,y)\),若当前 \(1\) 到 \(y\) 的最短距离是 \(p\),那么转移的时候相当于从点 \(y\) 走 \(k-p\) 步。显然 \(p\le 3\),那么这样的转移大概一次是 \(O(n^3)\) 的,然而我们一次更新能接受的复杂度是 \(O(n)\),于是无法接受。

容易一些的,我们首先考虑 \(p=2\) 的情形。考虑到最终会得到更新的也只有 \(n\) 个点,那么我们直接枚举这 \(n\) 个点 \(a\)。这时候我们需要知道从 \(y\) 到 \(a\) 恰好走 \(2\) 步的最短路 \(d_{y,a}\)。那这个东西由于限制了只走 \(2\) 步,是可以在更新每一条边的时候顺带预处理的。于是我们解决了 \(p=2\)。

对于 \(p=3\),不难发现现在更新一次的复杂度是 \(O(n^2)\),但是考虑到 \(p=3\) 时当且仅当 \(x=1\),也就是说只有 $n $ 个这样的更新,于是这样的复杂度还是 \(O(n^3)\) 的,可以通过。

其实这道题的核心是想到如何处理 \(p\le 3\) 时的情形。观察到距离为 \(2\) 可以做预处理时这题基本就做完了。

代码:

#include <bits/stdc++.h>
#define N 303
#define K 10
#define int long long
using namespace std;
int n, k;
int w[N][N];
struct node {
	int x, y;
} e[N * N];
int mp[N][N];
int f[N][K]; 
int g[N][K]; 
int d[N][N];
void cm(int &x, int y) {
	x = min(x, y);
}
int add(int x, int y) {
	int ans = 1e18 + 1;
	for (int ck = 0; ck <= 4; ck++)
		for (int a = 1; a <= n; a++)
			ans = min(ans, f[a][ck] + g[a][k - ck]);
	mp[x][y] = 1;
	for (int a = 1; a <= n; a++)
		if (mp[y][a])
			cm(d[x][a], w[x][y] + w[y][a]);
	for (int a = 1; a <= n; a++)
		if (mp[a][x])
			cm(d[a][y], w[a][x] + w[x][y]);
	for (int ck = 0; ck < 4; ck++)
		cm(f[y][ck + 1], f[x][ck] + w[x][y]);
	for (int ck = 0; ck < 4; ck++) {
		for (int a = 1; a <= n; a++)
			if (mp[y][a])
				cm(f[a][ck + 1], f[y][ck] + w[y][a]);
		for (int a = 1; a <= n; a++)
			cm(f[a][ck + 2], f[y][ck] + d[y][a]);
	} 
	if (x == 1) {
		for (int a = 1; a <= n; a++)
			for (int b = 1; b <= n; b++)
				if (mp[a][b])
					cm(f[b][4], f[a][3] + w[a][b]);
	} 
	for (int ck = 0; ck < 4; ck++)
		cm(g[x][ck + 1], g[y][ck] + w[x][y]);
	for (int ck = 0; ck < 4; ck++) {
		for (int a = 1; a <= n; a++)
			if (mp[a][x])
				cm(g[a][ck + 1], g[x][ck] + w[a][x]);
		for (int a = 1; a <= n; a++)
			cm(g[a][ck + 2], g[x][ck] + d[a][x]);
	} 
	if (y == n) {
		for (int a = 1; a <= n; a++)
			for (int b = 1; b <= n; b++)
				if (mp[b][a])
					cm(g[b][4], g[a][3] + w[b][a]);
	}
	return ans >= 1e18 ? -1 : ans;
}
stack<int>q;
signed main() {
	memset(f, 0x3f, sizeof f); 
	memset(g, 0x3f, sizeof g); 
	memset(d, 0x3f, sizeof d); 
	cin >> n >> k;
	f[1][0] = g[n][0] = 0;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			scanf("%lld",  &w[i][j]);
	for (int i = 1; i <= n * n; i++) 
		scanf("%lld%lld", &e[i].x, &e[i].y);
	for (int i = n * n; i; i--) 
		q.push(add(e[i].x, e[i].y));
	while (q.size())
		cout << q.top() << "\n", q.pop();
	return 0;
}

标签:Breakdown,0x3f,int,题解,P8906,memset,le,复杂度
From: https://www.cnblogs.com/Rock-N-Roll/p/18431937

相关文章

  • 题解:CF573D Bear and Cavalry
    因为这是远古题目,所以根据现在的评测机速度,用\(O(nq)\)的做法也是可以过的。也就是说,我们可以每次操作直接修改对应位置上的数字,然后设计一种\(O(n)\)的算法求解答案。这道题类似资源分配型动态规划,所以我们可以设\(dp_i\)表示分配前\(i\)个人的答案。直接写是不行的,我......
  • 题解:AT_abc204_e [ABC204E] Rush Hour 2
    变形的dijkstra。先思考什么情况下需要等待以及等待多长时间最优。我们把题目上的计算方法按照当前的时间\(t\)和通过所需的时间\(f(t)\)列个函数关系:\[f(t)=t+c+\lfloor\frac{d}{t+1}\rfloor\]然后用Desmos画个图可以得到图像(其实就是对勾函数):因为\(c,d\geq0\),所......
  • [湖北省选模拟 2023] 棋圣 / alphago 题解
    很牛的题目啊。-Alex_Wei发现这个操作比较复杂但限制较弱,考虑通过考察“不变的量”来刻画操作。容易发现若为二分图,则初始颜色不同的一定不能移动到一起。又因为在存在环的图上这个限制很弱/目前较难考虑,所以先考虑树的情况,发现答案存在可能取到的上界,令\(c_{i,j}\)为初......
  • CF1119H Triple 题解
    DescriptionSK酱送给你了一份生日礼物。礼物是\(n\)个三元组\((a_i,b_i,c_i)\)和四个正整数\(x,y,z,k\)。你利用这\(n\)个三元组填充了\(n\)个数组,其中第\(i\)个数组中有\(x\)个\(a_i\),\(y\)个\(b_i\),\(z\)个\(c_i\)(所以第\(i\)个数组长度为\((x+y+z)\)。......
  • Codeforces Round 974 (Div. 3)题解记录
    A.RobinHelps签到模拟,遍历一遍即可,注意没钱时不给钱。\(O(n)\)#include<iostream>#include<set>#include<map>#include<vector>#include<algorithm>#include<bitset>#include<math.h>#include<string>#include<string.h>#......
  • [ARC122E] Increasing LCMs 题解
    感觉像比较套路的构造题。思路假如我们正着进行构造,可以发现我们加入一个数以后,对后面的数产生的影响是很大的。但是如果我们从最后一个数开始构造,那么可以发现它是不会对之后的构造产生任何影响的。应为越前面的数的限制会越少,那么可以填的数一定是不减的。一个数可以填在后......
  • 算法题之图论 [NOIP2001 提高组] Car的旅行路线详细题解
    P1027[NOIP2001提高组]Car的旅行路线这道题的思路呢,就是建个图,然后跑一遍Floyd,比较最小值就可以解决了。but!它每个城市只给三个点(共四个),所以还得计算出第四个点坐标。这里根据矩形的中点公式来表示未知点的坐标:(这个思路源于大佬 _jimmywang_       ......
  • [ARC121E] Directed Tree 题解
    简单容斥题。思路题面的条件相当于一个位置上填的点不能是自己的祖先。发现直接做并不好做。考虑容斥。我们想要求出\(f_i\)为至少有\(i\)个不合法位置的方案数。那么答案为:\[\sum_{i=0}^nf_i(-1)^i\]如何求解。设\(f_{i,j}\)为\(i\)子树下有\(j\)个不合法位......
  • 2024-2025专题一题单 - 题解
    A-Virus原题链接题解B-Coverage原题链接题解C-Sensors原题链接题解D-MakeTakahashiHappy原题链接题解E-Don’tbecycle原题链接题解F-AlmostEqual原题链接题解G-StepUpRobot原题链接题解H-SnukeMaze原题链接题解I-MEX原题链接......
  • P5329 [SNOI2019] 字符串 题解
    Description给出一个长度为\(n\)的由小写字母组成的字符串\(a\),设其中第\(i\)个字符为\(a_i\(1\leqi\leqn)\)。设删掉第\(i\)个字符之后得到的字符串为\(s_i\),请按照字典序对\(s_1,s_2,……,s_n\)从小到大排序。若两个字符串相等,则认为编号小的字符串字典序更小。......