题解 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 旅行的主要内容,如果未能解决你的问题,请参考以下文章

P5022 旅行

旅行计划(题解)

[题解] [JSOI2010] 旅行

题解SDOI2014旅行

luogu P1137 旅行计划 题解

[JSOI2010]旅行题解