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} \) ...
随机推荐
- ef core 动态拼接 条件
var sql = new List<string>(); var sqlparams = new List<string>(); ; foreach (var p in ph ...
- 洛谷 P1578 奶牛浴场 题解
题面 1.定义有效子矩形为内部不包含任何障碍点且边界与坐标轴平行的子矩形.如图所示,第一个是有效子矩形(尽管边界上有障碍点),第二个不是有效子矩形(因为内部含有障碍点). 2.极大有效子矩形:一个有效 ...
- Luogu P3195 [HNOI2008]玩具装箱
题目 预处理\(C\)的前缀和\(sum\).设前\(i\)个物品的最小答案为\(f\). \(f_i=\max\limits_{j\in[1,i)}(f_j+(sum_i-sum_j-L)^2)\) ...
- css样式实例
* { box-sizing: border-box; } /*box-sizing属性允许您以特定的方式定义匹配某个区域的特定元素*/ body { font: Arial; margin:; } ...
- C++ 调用C语言、extern "C"、__cplusplus关键字
——C++编译器完全兼容C语言的编译方式.(但是得有源代码) ——C++编译器会优先使用C++的编译方式进行编译 ——extern "C" 关键字能够强制C++编译器进行C方式的编 ...
- type=file 上传图片限制 类型和尺寸 方法
<form> <input type="file" name="pic" id="pic" accept="im ...
- 第98:svd原理
SVD分解:任何矩阵都可以分解成第一行的形式,3个相乘.UV都是正交矩阵,中间的是奇异值. 3个相乘的形式可以拆分.即奇异值*第一行*第一列.在相加. 奇异值有时很小,在这种情况下,丢掉,可以减少计算 ...
- laravel 学习之第一章
LTS : long time support. download url : http://www.golaravel.com/download/ 第一篇 目录介绍: resource:包含了原 ...
- N皇后问题 回溯法 C/C++
一:问题描述 N皇后问题(含八皇后问题的拓展,规则同四皇后):在N*N的棋盘上,放置N个皇后,要求每一横行每一列,每一对角线上均只能放置一个皇后,求解可能的方案及方案数. 二:代码及结果如下 #inc ...
- 在VMware Vcenter添加一块网卡后,启动虚机找不到网卡,发现有一个ens38(redhat7.5)
添加一块网卡后,启动虚机找不到网卡,发现有一个ens38 问题:新建虚拟机设置为一块网卡,时候在Vcenter再添加一块网卡,这个问题相信很多网友都见过,今天就来总结一下添加过程中的问题. 由于有以前 ...