1 条题解

  • 1
    @ 2025-4-5 20:09:33

    题意:

    给出NN个点(不超过100100个),每个点有一个颜色(颜色标号不超过100100),有一些点的颜色可以相同。给出MM条有向边,这些边也有一个颜色。给出两个棋子的初始点L,KL,K,终点QQ,问两个棋子中的任意一个是否可以移动到QQ,如果可以,输出移动的最小步数。移动时遵循以下规则: 11.一个棋子可以移动到下一个点需要满足:经过的边的颜色与另一个棋子所在点的颜色相同; 22.只能沿着有向边的方向; 33.两个棋子不能同时移动到同一个点; 44.移动次序任意,没有必要交替进行; 55.其中一个棋子到达QQ点时游戏结束。

    思路:

    BFSBFS,注意判断两个棋子不能同时到同一个点。一个点有多条出边,数组要开得大一些。

    标程

    #include <cstdio>
    #include <iostream>
    #include <queue>
    #include <cstring>
    
    using namespace std;
    
    const int NUM = 105;
    const int INF = 0x3fffffff;
    
    struct Point {
        int color;          // 该点的颜色
        int cnt;            // 该点的出度
        int to[1005];       // 记录从该点出发的有向边
        int edgecolor[1005];    // 记录有向边的颜色
    
        void Get(int v, int color) {
            to[cnt] = v;
            edgecolor[cnt++] = color;
        }
    };
    
    Point point[NUM];
    
    int N, L, K, Q, ans;
    bool visit[NUM][NUM];
    
    struct Step {   // 记录每一步
        int first, second, cnt;   // 第一个棋子, 第二个棋子, 步数
    
        Step(int _f, int _s, int _c) {
            first = _f;
            second = _s;
            cnt = _c;
        }
    };
    
    queue<Step> q;
    
    bool Bfs() {
        Step temp(L, K, 0);
        visit[L][K] = true;
        q.push(temp);
        bool flag = false;    // 标记是否找到
    
        while (!q.empty()) {
            temp = q.front();
            q.pop();
            if (temp.first == Q || temp.second == Q) {
                flag = true;
                if (temp.cnt < ans)
                    ans = temp.cnt;
                break;
            }
            int i;
            Point curf = point[temp.first];
            Point curs = point[temp.second];
            for (i = 0; i < curf.cnt; i++) {
                if (visit[curf.to[i]][temp.second] == false && curf.to[i] != temp.second && curf.edgecolor[i] == curs.color) {
                    visit[curf.to[i]][temp.second] = true;
                    Step temp2(curf.to[i], temp.second, temp.cnt + 1);
                    q.push(temp2);
                }
            }
            for (i = 0; i < curs.cnt; i++) {
                if (visit[temp.first][curs.to[i]] == false && curs.to[i] != temp.first && curs.edgecolor[i] == curf.color) {
                    visit[temp.first][curs.to[i]] = true;
                    Step temp2(temp.first, curs.to[i], temp.cnt + 1);
                    q.push(temp2);
                }
            }
        }
        return flag;
    }
    
    void Init() {     // 初始化
        ans = INF;
        memset(point, 0, sizeof(point));
        memset(visit, false, sizeof(visit));
        while (!q.empty())
            q.pop();
    }
    
    int main() {
        int i, T;
        int u, v, color;
        while (scanf("%d%d%d%d", &N, &L, &K, &Q) != EOF) {
            Init();
            for (i = 1; i <= N; i++)
                scanf("%d", &point[i].color);
            scanf("%d", &T);
            for (i = 1; i <= T; i++) {
                scanf("%d%d%d", &u, &v, &color);
                point[u].Get(v, color);
            }
            if (Bfs())
                printf("YES\n%d\n", ans);
            else
                printf("NO\n");
        }
        return 0;
    }    
    
    
    • 1

    信息

    ID
    709
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者