Loading

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;
}
View Code

 

posted @ 2023-02-28 22:30  KakaDBL  阅读(34)  评论(0)    收藏  举报