码迷,mamicode.com
首页 > 其他好文 > 详细

P5151 HKE与他的小朋友 题解

时间:2019-08-20 22:39:23      阅读:122      评论:0      收藏:0      [点我收藏+]

标签:lan   节点   cto   cout   main   fine   htm   int   完整   

传送门:P5151

不难发现小朋友的运动是一种只和座位有关的有方向的运动,因此可以用点来存储座位,用有向边来存储小朋友的运动轨迹。

注意到点数等于边数,因此这张图只能是一个或多个环,才能满足所有人均能多次移动的性质。则问题可以简化为:给定一些环,求在环上运动 k 次后各点的位置。

那么可以很简单的想到判环。在这里直接使用 bfs 判环即可。在判环的同时,还要记录下每个环的大小 Ti? ,用于简化每个小朋友的位移量 xi = k mod Ti。并将每个环断开扔入一个链表里面,辅助后续查询。代码如下。

vector<int> list[MAXN];//存储环的链表,这里直接用vector代替
int land[MAXN][2];
//存储与环有关的数据
//第0维存储环的编号,第1位存储这该元素是环的第几号元素
int nxt[MAXN];//存下一个点的编号
int T[MAXN];//记录环的大小
int S[MAXN];//手写栈
int lis;//记录环的编号

void bfs1(int st){
    int x = st/*遍历环上的每一个节点*/, tops = 0/*栈顶*/,first = 1/*只是个标记*/;
    while (x != st || first){//遍历环
        first = 0;
        T[st]++;//环的大小增加
        list[lis].push_back(x);//把点扔到链表里
        land[x][0] = lis;
        land[x][1] = tops;//记录有关信息
        S[tops++] = x;//入栈
        x = nxt[x];//遍历下一个点
    }
    while (tops--){//修改每一个点记录的环大小
        T[ S[tops] ] = T[st];
    }//这里也可以不用栈存储,但是手写栈是最简单的。
    lis++;//环的编号增加
}

判环之后就是处理答案部分,但是要注意的一点是,这道题不是让你输出每个点在 k 次移动后的位置,而是 k 次移动后每个点上是原来的哪个点。很容易写出这样的代码。

int bfs2(int st, int k){
    int step = k % T[st];//计算有用的位移量
    step += land[st][1];//计算相对于环中一号点的位移量
    if (step >= T[st]) step -= T[st];//控制位移量在1 ~ T_i
    return list[ land[st][0] ][step];//返回该点坐标
}

for (int i = 1; i <= n; i++) ans[bfs2(i, k)] = i;
//枚举每个点,计算其结束坐标

这些工作都做完好,就可以愉快的切掉这道题了。

完整无修代码

#include <iostream>
#include <vector>
#define MAXN 100005
using namespace std;

vector<int> list[MAXN];
int land[MAXN][2];
int nxt[MAXN],T[MAXN],S[MAXN],ans[MAXN];
int lis;

void bfs1(int st){
    int x = st, tops = 0,first = 1;
    while (x != st || first){
        first = 0;
        T[st]++;
        list[lis].push_back(x);
        land[x][0] = lis;
        land[x][1] = tops;
        S[tops++] = x;
        x = nxt[x];
    }
    while (tops--){
        T[ S[tops] ] = T[st];
    }
    lis++;
}

int bfs2(int st, int k){
    int step = k % T[st];
    step += land[st][1];
    if (step >= T[st]) step -= T[st];
    return list[ land[st][0] ][step];
}

int main(){
    int n, k;
    cin>>n>>k;
    for (int i = 1; i <= n; i++) cin>>nxt[i];
    for (int i = 1; i <= n; i++) if (!T[i]) bfs1(i);
    for (int i = 1; i <= n; i++) ans[bfs2(i, k)] = i;
    for (int i = 1; i <= n; i++) cout<<ans[i]<<" ";
    return 0;
}

 

P5151 HKE与他的小朋友 题解

标签:lan   节点   cto   cout   main   fine   htm   int   完整   

原文地址:https://www.cnblogs.com/begin-AC/p/11385762.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!