zoukankan      html  css  js  c++  java
  • 100851K King’s Inspection

    传送门

    题目大意

    给你一张图,求这张图的汉密尔顿回路。

    分析

    因为m≤n+20,所以如果存在回路一定是在一个环中加入了至多20条边。我们先考虑dfs,但我们发现如果出现图1这种情况就会是复杂度爆炸

    图1图2

    我们发现如果有很多这样的三角形程序就会爆炸。所以我们考虑优化。我们发现对于所有出度为1的点我们完全不必枚举它的出边,所以根据这些就写出了代码1,然后它居然能水过,但是对于像图2这种数据它就只有被卡掉的份啦,所以我们考虑继续优化。我们考虑将所有只有一条路径的点从图中真实的去掉,也就是说我们将所有点的相连关系提前记录下来,以便后续输出答案,而在搜索过程中只考虑出度不为1的点,听起来可能有些麻烦,参照代码2看看写写就好理解了。

    代码1

    #include<bits/stdc++.h>
    using namespace std;
    vector<int>v[100050];
    int n,m,x[100050],y[100050],vis[100050],id[100050],od[100050],nxt[100050];
    int ans[100050];
    inline void bad(){
           puts("There is no route, Karl!");
           exit(0);
    }
    inline void dfs(int x){
           if(vis[x])return;
           vis[x]=1;
           for(int i=0;i<v[x].size();i++)dfs(v[x][i]);
    }
    inline void pr(){
          for(int i=0;i<=n;i++)
            printf(" %d",ans[i]);
          puts("");
          exit(0);
    }
    inline void search(int x,int cnt){
          if(cnt==n){
              ans[cnt]=x;
              if(x==1)pr();
              return;
          }
          if(vis[x])return;
          ans[cnt]=x;
          vis[x]=1;
          if(nxt[x]){
            search(nxt[x],cnt+1);
          }else {
              for(int i=0;i<v[x].size();i++){
                search(v[x][i],cnt+1);
              }
          }
          vis[x]=0;
          return;
    }
    int main(){
          freopen("king.in","r",stdin);
          freopen("king.out","w",stdout);
          scanf("%d%d",&n,&m);
          if(m<n)bad();
          for(int i=1;i<=m;++i){
              scanf("%d%d",&x[i],&y[i]);
              v[x[i]].push_back(y[i]);
          }
          memset(vis,0,sizeof(vis));
          dfs(1);
          for(int i=1;i<=n;i++)
            if(!vis[i])
              bad();
          for(int i=1;i<=n;i++)v[i].clear();
          for(int i=1;i<=m;i++){
              v[y[i]].push_back(x[i]);
          }
          memset(vis,0,sizeof(vis));
          dfs(1);
          for(int i=1;i<=n;i++)
            if(!vis[i])
              bad();
          for(int i=1;i<=n;i++)v[i].clear();
          for(int i=1;i<=m;i++){
              v[x[i]].push_back(y[i]);
            if(od[x[i]]==0)od[x[i]]=y[i];
              else if(od[x[i]]!=y[i])od[x[i]]=-1;
            if(id[y[i]]==0)id[y[i]]=x[i];
              else if(id[y[i]]!=x[i])id[y[i]]=-1;
          }
          for(int i=1;i<=n;i++)
            if(od[i]==0||id[i]==0)
              bad();
          for(int i=1;i<=n;i++)
            if(od[i]>0&&id[i]>0){
              nxt[i]=od[i];
              nxt[id[i]]=i;
            }
          memset(vis,0,sizeof(vis));
          search(1,0);
          bad();
          return 0;
    }

    代码2

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    #define sp cout<<"---------------------------------------------------"<<endl
    vector<int>v[110000];
    vector<int>cpx;
    int nxt[110000],vis[110000],arr[110000],n,m;
    inline void bad(){
           puts("There is no route, Karl!");
           exit(0);
    }
    inline void check(){
          int i,x;
          memset(arr,0,sizeof(arr));
          for(i=1,x=1;i<=n;i++,x=nxt[x]){
              if(arr[x])return;
              arr[x]=1;
          }
          for(i=1,x=1;i<=n;i++,x=nxt[x]){
              printf("%d ",x);
          }
          cout<<1<<endl;
          exit(0);
    }
    inline void work(int wh){
          if(wh==cpx.size()){
            check();
            return;
          }
          int x=cpx[wh];
          for(int i=0;i<v[x].size();i++)
            if(!vis[v[x][i]]){
              nxt[x]=v[x][i];
              vis[v[x][i]]=1;
              work(wh+1);
              vis[v[x][i]]=0;
            }
          return;
    }
    int main(){
          freopen("king.in","r",stdin);
          freopen("king.out","w",stdout);
          int i,j,k;
          scanf("%d%d",&n,&m);
          for(i=1;i<=m;i++){
              int x,y;
              scanf("%d%d",&x,&y);
              v[x].push_back(y);
          }
          for(i=1;i<=n;i++)
            if(v[i].empty())bad();
          for(i=1;i<=n;i++)
            if(v[i].size()>1){
              cpx.push_back(i);
            }else {
              if(vis[v[i][0]])bad();
              vis[v[i][0]]=1;
            }
          for(i=1;i<=n;i++)
            nxt[i]=v[i][0];
          work(0);
          bad();
          return 0;
    }
  • 相关阅读:
    Spark学习笔记——安装和WordCount
    Scala学习笔记——入门
    Scala学习笔记——安装
    Maven常用命令(转)
    maven中snapshot快照库和release发布库的区别和作用 (转)
    Hadoop学习笔记——WordCount
    Hadoop学习笔记——安装Hadoop
    机器学习——利用SVD简化数据
    Python自然语言处理学习——jieba分词
    机器学习——大数据与MapReduce
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9354283.html
Copyright © 2011-2022 走看看