E - Swap Places
一开始会想双端bfs,好像可写但是太麻烦,这个题的难点主要就是题目中两个颜色的限制。
正解是dp。dp[i][j]代表从1号店扩展的点到i,从n号点扩展的点到j的最短距离,然后题目存边的时候可以分开两类颜色去存,每个点的出边有两种,一种是颜色是red的另一种是颜色是blue的。然后bfs(今天才知道这种for循环的bfs写法)第一维枚举边的颜色第二三维分别枚举两种点的出边,如果他们的状态没被转移过那么就更新一下就好了。
上一个题貌似也是bfs加dp的想法,但是被我bfs硬艹过去了。
#include <bits/stdc++.h> using namespace std; #define gogo ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL); const string YES = "YES"; const string NO = "NO"; void run() { int n, m; cin >> n >> m; vector<int> c(n + 1); vector<vector<vector<int>>> edge(n + 1, vector<vector<int>> (2)); for (int i = 1;i <= n;i ++) cin >> c[i]; for (int i = 0;i < m;i ++) { int x, y; cin >> x >> y; edge[x][c[x]].push_back(y); edge[y][c[y]].push_back(x); } vector<vector<int>> dp(n + 1, vector<int> (n + 1, -1)); dp[1][n] = 0; vector<array<int, 2>> q; q.push_back({1, n}); for (int i = 0;i < (int)q.size();i ++) { auto [u, v] = q[i]; for (int d = 0;d < 2;d ++) for (auto x : edge[u][d]) for (auto y : edge[v][d ^ 1]) if (dp[x][y] == -1) { dp[x][y] = dp[u][v] + 1; q.push_back({x, y}); } } cout << dp[n][1] << '\n'; } int32_t main() { gogo; int tt; cin >> tt; while (tt --) run(); return 0; }

浙公网安备 33010602011771号