P5151 HKE与他的小朋友 题解
Posted begin-ac
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P5151 HKE与他的小朋友 题解相关的知识,希望对你有一定的参考价值。
传送门: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与他的小朋友 题解的主要内容,如果未能解决你的问题,请参考以下文章