题目链接 https://www.jisuanke.com/course/709/36590
题意:有n个点,m条边的联通图,有m个人落在任一点上,往周围走。每个人最多经过2n/k个点,要求每个点都要被经过至少一次,求怎么走?
B站题解 https://www.bilibili.com/video/av9249649?from=search&seid=12541065912944045953
题解:DFS搜索一遍整个图,形成一个DFS序列,这个序列有2n-1个节点,将其分割给每个人即可,多余的人就随便走。
比如有下面这个图,从1开始dfs,则dfs序列可以是1->2->4->5->3->5->4->2->1,假如k=3,则第一个人走1->2->4->5,第二人走3->5->4->2,剩下的人走1即可
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define MAXN 400020
using namespace std;
int n,m,k;
struct Edge {
int end;
int next;
Edge() {
next = -1;
}
} edge[MAXN];
int num = 0;// 记录边的数量
bool visited[MAXN];
int head[MAXN];
int sequence[2*MAXN+10];// 记录dfs序列
int snum = 0;
// 链式前向星加边
void Add(int s,int e) {
edge[num].next = head[s];
head[s] = num;
edge[num].end = e;
num++;
}
// DFS搜索
void DFS(int start) {
visited[start] = true;
sequence[snum++] = start;
int i = head[start];
// 搜索所有邻接点
for(;i != -1;i = edge[i].next) {
// 访问过的点
if(visited[edge[i].end]) continue;
DFS(edge[i].end);
sequence[snum++] = start;
}
}
int main() {
scanf("%d%d%d",&n,&m,&k);
for(int i = 1;i <= n;i++)
head[i] = -1;
int u,v;
for(int i = 0;i < m;i++) {
scanf("%d%d",&u,&v);
Add(u,v);
Add(v,u);
}
DFS(1);
int cnt = ceil(2*n*1.0/k);
int t = min(snum,cnt);
printf("%d ",t);
for(int i = 0;i < snum;i++) {
t--;
if(t > 0) {
printf("%d ",sequence[i]);
} else {
printf("%d\n",sequence[i]);
t = min(cnt,snum-i-1);
k--;
if(k && t > 0) {
printf("%d ",t);
}
}
}
if(k > 0) {
for(int i = 0;i < k;i++) printf("1 %d\n",1);
}
return 0;
}