传送门

题目大意

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

分析

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

图1图2

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

代码1

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

代码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[];
vector<int>cpx;
int nxt[],vis[],arr[],n,m;
inline void bad(){
puts("There is no route, Karl!");
exit();
}
inline void check(){
int i,x;
memset(arr,,sizeof(arr));
for(i=,x=;i<=n;i++,x=nxt[x]){
if(arr[x])return;
arr[x]=;
}
for(i=,x=;i<=n;i++,x=nxt[x]){
printf("%d ",x);
}
cout<<<<endl;
exit();
}
inline void work(int wh){
if(wh==cpx.size()){
check();
return;
}
int x=cpx[wh];
for(int i=;i<v[x].size();i++)
if(!vis[v[x][i]]){
nxt[x]=v[x][i];
vis[v[x][i]]=;
work(wh+);
vis[v[x][i]]=;
}
return;
}
int main(){
freopen("king.in","r",stdin);
freopen("king.out","w",stdout);
int i,j,k;
scanf("%d%d",&n,&m);
for(i=;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
}
for(i=;i<=n;i++)
if(v[i].empty())bad();
for(i=;i<=n;i++)
if(v[i].size()>){
cpx.push_back(i);
}else {
if(vis[v[i][]])bad();
vis[v[i][]]=;
}
for(i=;i<=n;i++)
nxt[i]=v[i][];
work();
bad();
return ;
}

100851K King’s Inspection的更多相关文章

  1. Codeforces Gym 100851 K King's Inspection ( 哈密顿回路 && 模拟 )

    题目链接 题意 : 给出 N 个点(最多 1e6 )和 M 条边 (最多 N + 20 条 )要你输出一条从 1 开始回到 1 的哈密顿回路路径,不存在则输出 " There is no r ...

  2. Gym 100851K

    Problem King's Inspection 题目大意 给一张n个点m条边的无向图,问是否存在一条欧拉回路. n<=10^5, 0<=m<=n+20. 解题分析 注意到数据范围 ...

  3. NEERC15

    2015-2016 ACM-ICPC Northeastern European Regional Contest 再开一个新坑吧 目前姿势有限,C.H.I仍然处于弃坑状态 代码戳这里 Problem ...

  4. Gym 100851 题解

    A: Adjustment Office 题意:在一个n*n的矩阵,每个格子的的价值为 (x+y), 现在有操作取一行的值,或者一列的值之后输出这个和, 并且把这些格子上的值归0. 题解:模拟, 分成 ...

  5. 2019-2020 Saint-Petersburg Open High School Programming Contest (SpbKOSHP 19)

    2019-2020 Saint-Petersburg Open High School Programming Contest (SpbKOSHP 19) easy: ABFGHI medium-ea ...

  6. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  7. [bzoj1087][scoi2005]互不侵犯king

    题目大意 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上 左下右上右下八个方向上附近的各一个格子,共8个格子. 思路 首先,搜索可以放弃,因为这是一 ...

  8. King's Quest —— POJ1904(ZOJ2470)Tarjan缩点

    King's Quest Time Limit: 15000MS Memory Limit: 65536K Case Time Limit: 2000MS Description Once upon ...

  9. 【状压DP】bzoj1087 互不侵犯king

    一.题目 Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上.下.左.右,以及左上.左下.右上.右下八个方向上附近的各一个格子,共8个格子. I ...

随机推荐

  1. dilworth定理的通俗讲解

    度娘定义:在数学理论中的序理论与组合数学中,Dilworth定理根据序列划分的最小数量的链描述了任何有限偏序集的宽度.其名称取自数学家Robert P. Dilworth. 反链是一种偏序集,其任意两 ...

  2. uva1605 - Building for UN(构造法)

    这道题构造出的结果很妙,考察思维能力.就两层,每层都n*n个格子,第一层第i行都放国家i,第二层第j列都放国家j. 需要注意的是ASCII中A至Z在a至z的前面(数字小),而且它们两组不挨着.所以需要 ...

  3. stl_hash_map.h

    stl_hash_map.h // Filename: stl_hash_map.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: ...

  4. 【转】Python获取当前系统时间

    转自:https://www.cnblogs.com/-ldzwzj-1991/p/5889629.html 取得时间相关的信息的话,要用到python time模块,python time模块里面有 ...

  5. java-10异常处理动手动脑

    1.请阅读并运行AboutException.java示例,然后通过后面的几页PPT了解Java中实现异常处理的基础知识. import javax.swing.*; class AboutExcep ...

  6. 还是畅通工程(peime算法最小生成树)

    个人心得:就是最小生成树的运用,还是要理解好每次都是从已搭建好的生成树里面选择与她的补集中最短距离,所以那个book数组的更新 需要好生体会.不过还是有缺陷,算法的复杂度为O(n^2),看介绍说用优先 ...

  7. Hive的JDBC访问

    实现hive查询源码: String driverName = "org.apache.hive.jdbc.HiveDriver"; try { Class.forName(dri ...

  8. [C++] 动态规划之矩阵连乘、最长公共子序列、最大子段和、最长单调递增子序列、0-1背包

    一.动态规划的基本思想 动态规划算法通常用于求解具有某种最优性质的问题.在这类问题中,可能会有许多可行解.每一个解都对应于一个值,我们希望找到具有最优值的解. 将待求解问题分解成若干个子问题,先求解子 ...

  9. 2018年长沙理工大学第十三届程序设计竞赛 E小木乃伊到我家(spfa模版)

    链接:https://www.nowcoder.com/acm/contest/96/E来源:牛客网 小木乃伊到我家 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他 ...

  10. JAVA生成Word文档(经过测试)

    首先告诉大家这篇文章的原始出处:http://www.havenliu.com/java/514.html/comment-page-1#comment-756 我也是根据他所描述完成的,但是有一些地 ...