782E. Underground Lab DFS 好题
题意:给出一个图,有n个点,m条边,k个人,每个人至多只能走$\lceil\frac{2n}{k}\rceil$步,输出可行的方案即输出每个人所走的步数和所走点
思路: 由于保证给出的是连通图,且每人$\lceil\frac{2n}{k}\rceil$的步数都用完的话,显然必定有答案。那么我们不妨构造一个DFS的遍历序列(包括回溯的过程),那么最后对这个序列进行分配即可,如果图已经走完,而还有人没走,那么直接输出 1 1 即可
/** @Date : 2017-05-10 18:06:33 * @FileName: 782E DFS.cpp * @Platform: Windows * @Author : Lweleth (SoundEarlf@gmail.com) * @Link : https://github.com/Lweleth * @Version : $Id$ */ #include <bits/stdc++.h> #define LL long long #define PII pair #define MP(x, y) make_pair((x),(y)) #define fi first #define se second #define PB(x) push_back((x)) #define MMG(x) memset((x), -1,sizeof(x)) #define MMF(x) memset((x),0,sizeof(x)) #define MMI(x) memset((x), INF, sizeof(x)) using namespace std; const int INF = 0x3f3f3f3f; const int N = 1e5+20; const double eps = 1e-8; int n, m, k; vector vt[2*N]; int a[2*N]; int ans[2*N]; bool vis[N]; int cnt = 0; void dfs(int x) { vis[x] = 1; a[cnt++] = x; int l = vt[x].size(); for(int i = 0; i < l; i++) { int np = vt[x][i]; if(vis[np]) continue; dfs(np); a[cnt++] = x;//模拟回溯 } } int main() { while(cin >> n >> m >> k) { for(int i = 0; i < m; i++) { int x, y; scanf("%d%d", &x, &y); vt[x].PB(y); vt[y].PB(x); } int ma = 2*n/k + ((2*n)%k?1:0); MMF(vis); cnt = 0; dfs(1); int cc = 0; for(int i = 0; i < cnt; i++) { //cout << a[i]<<"~"; if(cc < ma) ans[cc++] = a[i]; else { k--; printf("%d ", ma); for(int j = 0; j < cc; j++) printf("%d%s", ans[j], j==cc-1?"\n":" "); cc = 0; ans[cc++] = a[i]; } } if(cc > 0) printf("%d ", cc), k--; for(int i = 0; i < cc; i++) printf("%d%s", ans[i], i==cc-1?"\n":" "); for(int i = 0; i < k; i++) printf("1 1\n"); } return 0; }