Codeforces Gym 100851 K King's Inspection ( 哈密顿回路 && 模拟 )
题意 : 给出 N 个点(最多 1e6 )和 M 条边 (最多 N + 20 条 )要你输出一条从 1 开始回到 1 的哈密顿回路路径,不存在则输出 " There is no route, Karl! "
分析 :
题意很简单明了
众所周知,哈密顿回路是个 NP-Hard 问题
这么多个点的哈密顿回路肯定是不能暴力去寻找的
但是关注到 M ≤ N + 20 这个特殊的条件
那就说明图中肯定有很多单向链
那么这题就很明确了,就把所有的单链缩成一个点
然后再去 DFS 暴力找
口胡起来貌似很简单,写起来是真的 _(´ཀ`」 ∠)_
写了我挺久的,主要是Debug了挺久
#include<bits/stdc++.h> using namespace std; ; ]; ];///记录链的出度和入度 int N, M, Head[maxn], cnt; int id, st;///分配ID的计数变量、寻找哈密顿回路的起点 int IN[maxn], OUT[maxn];///每个点的入度和出度数量,方便判断一个节点是否为单链的节点 int ID[maxn], vtx[maxn];///每个节点重新分配的ID、每个ID对应的节点or链 bool isChain[maxn], vis[maxn];///判断是否是链、DFS中的判重数组 int c[maxn];///并查集数组,判断图是否弱连通 vector<int> arr;///存储最终答案 int Findset(int x) { int root = x; while(c[root] != root) root = c[root]; int idx; while(c[x] != root){ idx = c[x]; c[x] = root; x = idx; } return root; } inline void Join(int a, int b) { int A = Findset(a); int B = Findset(b); if(A != B) c[A] = B; } inline void init() { ; i<maxn; i++) c[i] = i; memset(ID, -, sizeof(ID)); memset(vtx, -, sizeof(vtx)); memset(Head, -, sizeof(Head)); memset(isChain, false, sizeof(isChain)); cnt = id = ; st = -; } inline void AddEdge(int From, int To) { Edge[cnt].v = To; Edge[cnt].nxt = Head[From]; Head[From] = cnt++; } inline void ColorChain(int v, int Eiv, int Eid) { Chain[id][] = v; bool loop = false;///链有可能构成环、如果是环,则出入度是一样的,标记一下 || OUT[Eiv] != )){ ) { ID[Eiv] = id; ) vtx[id] = Eiv; } else { loop = true; break; } isChain[Eiv] = true; Eiv = Edge[Eid].v; Eid = Head[Eiv]; } Chain[id][] = loop ? v : Eiv; id++; } inline void Color(int v) { && OUT[v] == ) return;///如果是单链上的节点就跳过,因为我的染色找链 ///总是去找链的入度节点才去为这个链分配ID Chain[id][] = v, Chain[id][] = -;///可以无视这个,没啥用 ID[v] = id++; vtx[id-] = v; int Eid, Eiv; ; i=Edge[i].nxt){ Eiv = Edge[i].v; Eid = i; && OUT[Eiv] == )///说明v是一个链的入度 ColorChain(v, Eiv, Head[Eiv]);///为链染色 } } int ans[maxn]; bool DFS(int v, int num)///寻找哈密顿回路,分是否是链的两种情况 { if(num == id && v == st) return true; if(vis[ID[v]]) return false; vis[ID[v]] = true; ans[num] = ID[v]; if(isChain[v]){ ], num+) )///如果是链的开头,直接递归进其出度 return true; }else{ ; i=Edge[i].nxt)///如果不是链则正常访问其所有出度 ) ) return true;; } vis[ID[v]] = false; return false; } inline void Print_Chain(int v, int Chain_id) { && OUT[v]==){ arr.push_back(v); v = Edge[Head[v]].v; } } int main(void) { freopen("king.in", "r", stdin);///提交记得加这两个 freopen freopen("king.out", "w", stdout); scanf("%d %d", &N, &M); init(); int From, To; while(M--){ scanf("%d %d", &From, &To); AddEdge(From, To); Join(From, To); IN[To]++, OUT[From]++; } ); ; i<=N; i++){ if(Findset(i) != root){ puts("There is no route, Karl!"); ; } } ; i<=N; i++){ && (IN[i] != || OUT[i] != )) st = i; ) continue; else Color(i);///给每一个点配上一个ID,如果是链,则链上顶点ID一致, ///且当前节点 isChain = true 标记是链 } ){ ; bool flag = true; ){ flag = false; printf("%d ", v); v = Edge[Head[v]].v; }puts("); ; } memset(vis, false, sizeof(vis)); )){ ; i<id; i++){ int cur = vtx[ans[i]]; if(isChain[cur]) Print_Chain(cur, ans[i]); else arr.push_back(cur); } bool BEGIN = false; ; int len = arr.size(); ; i<len && Count<len; i=(i+)%len){///因为不保证总是从1开始dfs,所以要去调整一下输出 ) BEGIN = true; if(BEGIN){ printf("%d ", arr[i]); Count++; } }puts("); }else puts("There is no route, Karl!"); ; } /* 10 11 10 8 5 4 9 1 4 3 7 2 2 6 6 5 8 9 1 7 10 3 3 10 */
Codeforces Gym 100851 K King's Inspection ( 哈密顿回路 && 模拟 )的更多相关文章
- 【二分】NEERC15 L Landscape Improved(2015-2016 ACM-ICPC)(Codeforces GYM 100851)
题目链接: http://codeforces.com/gym/100851 题目大意: 一个宽度为N的网格图,i上有h[i]高的方块.现在你有W个方块,问怎么放使得最终的最高点最高. 只要一个格子的 ...
- 【模拟】NEERC15 G Generators(2015-2016 ACM-ICPC)(Codeforces GYM 100851)
题目链接: http://codeforces.com/gym/100851 题目大意: n个序列.每个序列有4个值x,a,b,c,之后按照x=(a*x+b)%c扩展无穷项. 求每个序列各取一个数之后 ...
- 【模拟】NEERC15 J Jump(2015-2016 ACM-ICPC)(Codeforces GYM 100851)
题目链接: http://codeforces.com/gym/100851 题目大意: 系统里生成一个字符串C,一开始告诉你字符串的长度N(偶数).接着你需要在n+500次内猜出这个字符串是什么. ...
- 【最短路】NEERC15 F Froggy Ford(2015-2016 ACM-ICPC)(Codeforces GYM 100851)
题目链接: http://codeforces.com/gym/100851 题目大意: 一只青蛙跳过宽为W的河,河中游N个石头,坐标xi,yi,现在往河中间添加一个石头,使得每次跳跃的最大的距离最小 ...
- 【模拟】NEERC15 E Easy Problemset (2015-2016 ACM-ICPC)(Codeforces GYM 100851)
题目链接: http://codeforces.com/gym/100851 题目大意: N个人,每个人有pi个物品,每个物品价值为0~49.每次从1~n顺序选当前这个人的物品,如果这个物品的价值&g ...
- 【模拟】NEERC15 A Adjustment Office (2015-2016 ACM-ICPC)(Codeforces GYM 100851)
题目链接: http://codeforces.com/gym/100851 题目大意: 一个N*N的矩阵A,Ai,j=i+j,Q次操作,每次分两种,R r取出第r行还未被取的所有数,并输出和.C c ...
- Codeforces Gym 100187K K. Perpetuum Mobile 构造
K. Perpetuum Mobile Time Limit: 2 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/pro ...
- codeforces gym 100971 K Palindromization 思路
题目链接:http://codeforces.com/gym/100971/problem/K K. Palindromization time limit per test 2.0 s memory ...
- CF gym 101933 K King's Colors —— 二项式反演
题目:http://codeforces.com/gym/101933/problem/K 其实每个点的颜色只要和父亲不一样即可: 所以至多 i 种颜色就是 \( i * (i-1)^{n-1} \) ...
随机推荐
- adb将Apk内置到系统中(system/priv-app)
https://blog.csdn.net/starhosea/article/details/78697007 so文件的处理是目前遇到过的问题.文章中解释了. 正文: 有时候我们在Android ...
- poj2407(欧拉函数模板题)
题目链接:https://vjudge.net/problem/POJ-2407 题意:给出n,求0..n-1中与n互质的数的个数. 思路:欧拉函数板子题,先根据唯一分解定理求出n的所有质因数p1,p ...
- 【洛谷p1781】宇宙总统
宇宙总统[题目链接] 关于题目算法,其实就是考排序,那我们直接sort不就好啦,显然不能. 这个题让我重新认识了cmp函数: 以下是我的心路历程: 看到这个题,嗯?这么简单的吗,我直接sort不就好啦 ...
- Spring Data Elasticsearch基本使用
目录 1. 创建工程 2. 配置application.yaml文件 3. 实体类及注解 4. 测试创建索引 5. 增删改操作 5.1增加 5.2 修改(id存在就是修改,否则就是插入) 5.3 批量 ...
- laravel框架之批刪&全選&全不選&反選
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 拉勾网python开发要求爬虫
#今日目标 **拉勾网python开发要求爬虫** 今天要爬取的是北京python开发的薪资水平,招聘要求,福利待遇以及公司的地理位置. 通过实践发现除了必须携带headers之外,拉勾网对ip访问频 ...
- Leaving Auction CodeForces - 749D (set,贪心,模拟)
大意: 若干个人参加拍卖会, 给定每个人出价顺序, 保证价格递增, q个询问, 给出k个人的编号, 求删除这k个人的所有出价后, 最终谁赢, 他最少出价多少. set维护每个人最后一次投票的时间, 每 ...
- Oracle及SQLPLUS使用笔记
Oracle及SQLPLUS使用笔记 自己之前粗粗的学过MySQL,学校用的是Oracle,学生使用sqlplus,这是个命令行界面的数据库管理软件(为了学习嘛,不用图形化可以理解),这里记录一些使用 ...
- node.js中使用imagemagick进行图片裁剪压缩
node.js中使用imagemagick进行图片裁剪压缩 安装imagemagick sudo apt-get install imagemagick or wget http://www.imag ...
- call apply bind sleep
1.自己实现一个call 1)利用对象的方式的形式改变this指针 funcion add; add.call(temObj) 只需要 在temObj对象临时添加一个方法即可 Function.pro ...