长沙学院20级训练赛-原魔题解

长沙学院20级训练赛-原魔题解,第1张

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网

题目描述

众所周知,原魔是全宇宙最好的游戏。


最近原魔出了一个策划模拟器,许多魔鬼策划在里面疯狂彰显才能,尽情的虐待旅行者。


有这么一个萌新策划,她设置出了一个简单的地图,该地图有n个房间,她给每两个房间之间建了一条通道,该通道可以双向同行,但她觉得这样太简单了,决定加大难度,于是,她就拆掉了其中一些路,并想把终点设置在离起点最远的一间房间里,但她不知道那个最远,于是她向你求助,她告诉你了起点在哪个房间以及她拆掉了那些路,现在请你告诉她每个房间到起点的距离,并且告诉他哪个房间离起点最远,如果某个房间不能到达则输出-1。


输入描述:

第一行输入两个整数n,m,分别代表房间数,拆除的通道数。


(n<=2e4,m<=1e5)

第二行输入一个整数S,表示起点房间的编号。


(S∈[1,n])

第三行开始m行,每行两个整数a,b,表示房间a与房间b之间的通道被拆除了。


(a,b∈[1,n],且a≠b)

输出描述:

输出共两行,第一行输出n个整数,表示每个房间到起点的距离,第二行一个整数,表示离起点最远的那个房间,如果最远的房间有多个,输出编号最小的那个。


示例1

输入

4 2 1 1 4 2 4

4 2
1
1 4
2 4
输出

0 1 1 2 4

0 1 1 2
4
解题思路:

通过本题的描述,很容易看出就是一个简单的bfs能解决的问题,但题目给的是一个补图,要想跑bfs就得建出正图,而建正图的复杂度是O(n^2),有亿点高,题目给的n的范围是2e4,要建正图绝对是超时了,这时我们发现,题目给的m很小,说明补图很小,既然这样,为什么不在补图上跑bfs呢?那又要怎么在补图上bfs呢?在这里我们要用到STL中的set,用set来维护图中还有那些点没跑到,在跑到这个点时,把与这个点在补图中有边的点放到未跑到的点集中,剩下的就是与之相连的点了,接下来就是正常的bfs就行了。


过题代码:
#include
using namespace std;
#define Inf 1e9+7
const int N = 2e4 + 10;
const int M = 1e5 + 10;

int n, m;
int S, T;
int e[M], w[M], ne[M], h[N], idx;
int A[N];
int dis[N];
int q[N];
bitsetvis;

void add(int a, int b) {
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}

void bfs() {
    int hh = 0, tt = 0;
    q[0] = S;
    sets1, s2;
    for (int i = 1;i <= n;i++) {
        if (i != S) {
            s1.insert(i);
        }
    }
    while (hh <= tt) {
        int t = q[hh++];
        for (int i = h[t];~i;i = ne[i]) {
            int y = e[i];
            s1.erase(y);
            s2.insert(y);
        }
        for (set::iterator it = s1.begin();it != s1.end();it++) {
            if (vis[*it]) {
                continue;
            }
            vis[*it] = 1;
            dis[*it] = dis[t] + 1;
            q[++tt] = *it;
        }
        s1.swap(s2);
        s2.clear();
    }
}

int main() {
        memset(dis, Inf, sizeof(dis));
        vis.reset();
        memset(h, -1, sizeof(h));
        idx = 0;
        scanf("%d %d", &n, &m);
        scanf("%d", &S);
        while (m--) {
            int a, b;
            scanf("%d %d", &a, &b);
            add(a, b);
            add(b, a);
        }
        dis[S] = 0;
        bfs();
        int ma = -1;
        int x = S;
        for (int i = 1;i <= n;i++) {
            if (dis[i] >= Inf) {
                printf("-1 ");
            }
            else {
                printf("%d ", dis[i]);
                if (ma < dis[i]) {
                    ma = dis[i];
                    x = i;
                }
            }
        }
        printf("\n%d\n", x);
}

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/607206.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-04-14
下一篇2022-04-14

发表评论

登录后才能评论

评论列表(0条)

    保存