zoukankan      html  css  js  c++  java
  • 洛谷 P5022 旅行(DFS+断环)

    题目链接:https://www.luogu.com.cn/problem/P5022

    首先对于m=n-1的情况非常好想:即这是一棵树,然后从1节点开始,搜一遍。注意要搜出来的序列的字典序最小,所以用邻接矩阵来存储,存的时候按当前节点能到的节点的编号从小到大排序。

    当m=n的时候:这时候便是一个基环树,在树上的某一个地方会有一个环,会发现环上的有一条边是不会走的。然而并不确定这条边到底是哪一条,所以进行枚举断环。但找出环来太麻烦,所以可以直接枚举m条边中哪一条边不会走,每次看能否将n个点都走一遍,即cnt是否等于n。如果都能走,则每次更新字典序最小的ans。

    关于将一条边断掉:不需要考虑复杂,只需要假设断掉的边的两个端点分别为x,y,在DFS时,如果当前的边的端点恰好是x,y,则直接continue即可。

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<vector>
     5 #include<algorithm>
     6 using namespace std;
     7 const int N=5010;
     8 vector<int> a[N];
     9 int cnt,tot,x,y,n,m;
    10 struct node{
    11     int to,from,next;
    12 }edge[N<<1];
    13 int head[N],k[N],ans[N],vis[N];
    14 void add(int u,int v){
    15     edge[tot].to=v;
    16     edge[tot].from=u;
    17     edge[tot].next=head[u];
    18     head[u]=tot++;
    19 }
    20 void change(){
    21     for(int i=1;i<=n;i++) ans[i]=k[i];
    22 }
    23 bool check(){
    24     for(int i=1;i<=n;i++){
    25         if(k[i]<ans[i]) return 1;
    26         else if(k[i]>ans[i]) return 0;
    27         else continue;
    28     }
    29 }
    30 void work(int u,int fa){
    31     if(vis[u]) return;
    32     vis[u]=1;
    33     ans[++cnt]=u;
    34     for(int i=0;i<a[u].size();i++){
    35         int v=a[u][i];
    36         if(v==fa) continue;
    37         work(v,u);
    38     }
    39 }
    40 void DFS(int u,int fa){
    41     if(vis[u]) return;
    42     vis[u]=1;
    43     k[++cnt]=u;
    44     for(int i=0;i<a[u].size();i++){
    45         int v=a[u][i];
    46         if(v==fa) continue;
    47         if((v==x&&u==y)||(v==y&&u==x)) continue;
    48         DFS(v,u);
    49     }
    50 }
    51 int main(){
    52     memset(head,-1,sizeof(head));
    53     scanf("%d%d",&n,&m);
    54     for(int i=1;i<=m;i++){
    55         int u,v;
    56         scanf("%d%d",&u,&v);
    57         a[u].push_back(v); a[v].push_back(u);
    58         add(u,v); add(v,u);
    59     }
    60     for(int i=1;i<=n;i++) sort(a[i].begin(),a[i].end());
    61     if(n==m){
    62         for(int i=0;i<tot;i+=2){
    63             cnt=0; x=edge[i].from; y=edge[i].to;
    64             memset(vis,0,sizeof(vis));
    65             DFS(1,-1);
    66             if(cnt<n) continue;
    67             if(ans[1]==0) change();
    68             else if(check()) change();
    69         }
    70         for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    71         return 0;
    72     }
    73     work(1,-1);
    74     for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    75     return 0;
    76 }
    AC代码
  • 相关阅读:
    hdoj:2033
    hdoj:2032
    hdoj:2031
    hdoj:2029
    hdoj:2028
    hdoj:2027
    hdoj:2024
    hdoj:2023
    hdoj:2022
    hdoj:题目分类
  • 原文地址:https://www.cnblogs.com/New-ljx/p/13832694.html
Copyright © 2011-2022 走看看