题解 P5022 旅行
Posted yuanqiqhfz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 P5022 旅行相关的知识,希望对你有一定的参考价值。
题解 P5022 【旅行】
一道基环树的题记得我当时在考场连dfs都没想到(我真的是太弱了QAQ)
这道题知道思路其实很简单,当n = m - 1时,图是一个树,直接从第一个点dfs就可以得到答案,n = m时说明图里有一个环,删掉环上的任意一条边就可以让图变成一个数,枚举删除那一条边得到的答案字典序最小即可。
我们老师刚学图就让我们做这道题,总之我觉得用来练习图的基本操作是极好的。这道题我大概交了十几遍才过,因为dfs要求先访问编号最小的节点,所以我第一次一上来用邻接矩阵存图,结果T飞了想想为什么,后来吭哧吭哧自学了邻接链表结果忘了排序......最后做足了功课上std,又T了三个点很明显为什么
仔细琢磨了一下发现一个小优化,在n = m时,当我们删除了一条边开始dfs(答案存在res数组里),如果我们发现res[u] > ans[u], 则res一定不比ans优,可以直接跳出,然后你就可以AC最后三个点了。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define ll long long
#define N 5005
using namespace std;
int n, m, tot, vis[N], ans[N], res[N], inp[N][2];
bool ian = 0; //代表res中的答案是否比ans优
vector < int > mp[N];
inline int read()
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') if (c == '-') f = -1; c = getchar();
while (c >= '0' && c <= '9') x = x * 10 + c - '0'; c = getchar();
return x * f;
void addedge(int x, int y)
mp[x].push_back(y);
mp[y].push_back(x);
void dfs(int x, int d1, int d2) //d1 d2 表示删除的边连接的节点
vis[x] = true;
res[++tot] = x;
if (x < ans[tot]) ian = true; //如果res[x] < ans[x],则无论res后面是什么,res都一定比ans优
if (x > ans[tot] && !ian) vis[x] = false; return; //如果res[x] > ans[x] 且x前面的答案都一样,则res一定没有ans优
int l = mp[x].size();
for (int i = 0; i < l; i++)
if (!vis[mp[x][i]] && !((x == d1 && mp[x][i] == d2) || (x == d2 && mp[x][i] == d1)))
dfs(mp[x][i], d1, d2);
vis[x] = false;//别忘了把值赋回去
int main()
memset(ans, 0x3f3f3f, sizeof(ans));
n = read(), m = read();
for (int i = 1; i <= m; i++)
addedge(inp[i][0] = read(), inp[i][1] = read());
for (int i = 1; i <= n; i++)
sort(mp[i].begin(), mp[i].end()); //一定别忘了排序,不然dfs出来的不一定字典序最小
if (n == m)//有环
for (int i = 1; i <= m; i++)//枚举删边
tot = 0, ian = false;
dfs(1, inp[i][0], inp[i][1]);
if (tot != n) continue;
int flag = false; //res比ans更优
for (int i = 1; i <= n; i++)
if (res[i] < ans[i]) flag = true; break;
else if (res[i] > ans[i]) break;
//看看ans和res哪一个更优
if (flag)//如果res更优则把res赋给ans
for (int i = 1; i <= n; i++)
ans[i] = res[i];
else//没有环
dfs(1, 0, 0);
for (int i = 1; i <= n; i++)
ans[i] = res[i];
for (int i = 1; i <= n; i++)
cout << ans[i] << " ";//输出答案
return 0;
19.08.18
以上是关于题解 P5022 旅行的主要内容,如果未能解决你的问题,请参考以下文章