题目链接

BZOJ4727

题解

前置芝士

1.竞赛图存在哈密顿路径

2.竞赛图存在哈密顿回路,当且仅当它是强联通的

所以我们将图缩点后,拓扑排序后一定是一条链,且之前的块内的点和之后块内的点的边一定全都由前面指向后面

而每个块都是强联通的,所以我们从起点出发,一定能找到一条路径走完后面所有点

我们只需预处理出每个强联通块内的一条哈密顿回路,就可以求出答案了

现在问题转化成了求竞赛图的哈密顿回路

我们先求出一条哈密顿路径

哈密顿路径

从竞赛图中任意一个点出发向外扩展,维护一个链表

假若扩展到点\(u\)

1.如果\(u\)指向链头或链尾,直接加入链表

2.否则链的中间一定存在相邻两点,使得\(i\)指向\(u\),\(u\)指向\(i + 1\),这时候把\(u\)插入之间即可

哈密顿回路

我们在哈密顿路径的基础上构造哈密顿回路

首先如果存在如图情况,前\(4\)个点构成回路



我们先找到最大的一个这样的回路,然后只需处理后面不在圈内的几个点

对于一个点\(u\),如果存在一条\(u\)指向圈内点的边,那么\(u\)可以插入圈内

否则跳过\(u\),将\(u\)和之后插入圈内的点一起插入圈内

由于图是强联通的,所以最后一定能全部加入

复杂度\(O(n^2)\)

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cstdio>
  6. #include<vector>
  7. #include<queue>
  8. #include<cmath>
  9. #include<map>
  10. #define LL long long int
  11. #define REP(i,n) for (register int i = 1; i <= (n); i++)
  12. #define cls(s,v) memset(s,v,sizeof(s))
  13. #define mp(a,b) make_pair<int,int>(a,b)
  14. #define cp pair<int,int>
  15. #define res register
  16. using namespace std;
  17. const int maxn = 2005,maxm = 100005,INF = 0x3f3f3f3f;
  18. inline int read(){
  19. int out = 0,flag = 1; char c = getchar();
  20. while (c < 48 || c > 57){if (c == '-') flag = 0; c = getchar();}
  21. while (c >= 48 && c <= 57){out = (out << 1) + (out << 3) + c - 48; c = getchar();}
  22. return flag ? out : -out;
  23. }
  24. int tmp[20],ti;
  25. inline void write(int x){
  26. ti = 0;
  27. while (x) tmp[++ti] = x % 10,x /= 10;
  28. while (ti) putchar('0' + tmp[ti--]);
  29. }
  30. vector<int> S[maxn];
  31. int n,G[maxn][maxn];
  32. int dfn[maxn],low[maxn],Scc[maxn],st[maxn],top,cnt,scci;
  33. int nxt[maxn],head[maxn],tail[maxn];
  34. int Nxt[maxn],Head[maxn],Tail[maxn];
  35. int g[maxn][maxn],de[maxn],q[maxn],hh,tt;
  36. int tp[maxn],pos[maxn],ans[maxn],ansi,tot;
  37. int c[maxn],ci;
  38. void dfs(int u){
  39. dfn[u] = low[u] = ++cnt;
  40. st[++top] = u;
  41. for (res int to = 1; to <= n; to++){
  42. if (!G[u][to]) continue;
  43. if (!dfn[to]){
  44. dfs(to);
  45. low[u] = min(low[u],low[to]);
  46. }
  47. else if (!Scc[to]) low[u] = min(low[u],dfn[to]);
  48. }
  49. if (low[u] == dfn[u]){
  50. scci++;
  51. do{
  52. Scc[st[top]] = scci;
  53. S[scci].push_back(st[top]);
  54. }while (st[top--] != u);
  55. }
  56. }
  57. void workline(){
  58. int siz;
  59. for (res int p = 1; p <= scci; p++){
  60. siz = S[p].size();
  61. head[p] = tail[p] = S[p][0];
  62. for (res int i = 1; i < siz; i++){
  63. int u = S[p][i];
  64. if (G[u][head[p]]) nxt[u] = head[p],head[p] = u;
  65. else if (G[tail[p]][u]) nxt[tail[p]] = u,tail[p] = u;
  66. else for (res int j = head[p]; j; j = nxt[j])
  67. if (G[j][u] && G[u][nxt[j]]){
  68. nxt[u] = nxt[j]; nxt[j] = u; break;
  69. }
  70. }
  71. }
  72. }
  73. void workcir(){
  74. int p,last;
  75. for (int i = 1; i <= scci; i++){
  76. ci = 0; p = 1;
  77. for (int k = head[i]; k; k = nxt[k]) c[++ci] = k;
  78. for (int k = ci; k; k--)
  79. if (G[c[k]][head[i]]) {p = k; break;}
  80. Head[i] = c[1]; Tail[i] = c[p];
  81. for (int k = 1; k < p; k++) Nxt[c[k]] = c[k + 1];
  82. last = c[p + 1];
  83. for (int k = p + 1; k <= ci; k++){
  84. int u = c[k],flag = false;
  85. for (int j = Nxt[Head[i]],pre = Head[i]; j; j = Nxt[pre = j])
  86. if (G[u][j]){
  87. Nxt[pre] = last;
  88. Nxt[u] = j;
  89. flag = true;
  90. break;
  91. }
  92. if (flag) last = c[k + 1];
  93. else Nxt[u] = c[k + 1];
  94. }
  95. Nxt[Tail[i]] = Head[i];
  96. }
  97. }
  98. void work(){
  99. for (res int i = 1; i <= n; i++){
  100. int u = Scc[i];
  101. for (res int j = 1; j <= n; j++)
  102. if (G[i][j] && Scc[j] != u && !g[u][Scc[j]])
  103. de[Scc[j]]++,g[u][Scc[j]] = 1;
  104. }
  105. for (res int i = 1; i <= scci; i++) if (!de[i]) q[++tt] = i;
  106. int u; hh = 1;
  107. while (hh <= tt){
  108. u = q[hh++]; pos[u] = ++tot; tp[tot] = u;
  109. for (int i = 1; i <= scci; i++) if (g[u][i]){
  110. if (!(--de[i])) q[++tt] = i;
  111. }
  112. }
  113. for (res int u = 1; u <= n; u++){
  114. int s = Scc[u];
  115. ans[ansi = 1] = u;
  116. for (res int i = Nxt[u]; i != u; i = Nxt[i]) ans[++ansi] = i;
  117. for (res int j = pos[s] + 1; j <= scci; j++){
  118. int t = tp[j];
  119. ans[++ansi] = Head[t];
  120. for (res int i = Nxt[Head[t]]; i != Head[t]; i = Nxt[i])
  121. ans[++ansi] = i;
  122. }
  123. write(ansi); putchar(' ');
  124. for (res int i = 1; i <= ansi; i++){
  125. write(ans[i]);
  126. if (i < ansi) putchar(' ');
  127. }
  128. puts("");
  129. }
  130. }
  131. int main(){
  132. n = read();
  133. for (res int i = 2; i <= n; i++)
  134. for (res int j = 1; j < i; j++)
  135. G[i][j] = ((G[j][i] = read()) ^ 1);
  136. REP(i,n) if (!dfn[i]) dfs(i);
  137. workline();
  138. //puts("LXT");
  139. workcir();
  140. //puts("LXT");
  141. work();
  142. return 0;
  143. }

BZOJ4727 [POI2017]Turysta 【竞赛图哈密顿路径/回路】的更多相关文章

  1. bzoj千题计划232:bzoj4727: [POI2017]Turysta

    http://www.lydsy.com/JudgeOnline/problem.php?id=4727 竞赛图tarjan缩点后得到的拓扑图一定是一条链 因为竞赛图任意两点的前后顺序确定,只有一种拓 ...

  2. BZOJ4727 [POI2017]Turysta

    这题太神了还是去看刺儿神题解吧. http://www.cnblogs.com/neighthorn/p/6538364.html #include <cstdio> #include & ...

  3. BZOJ 4727: [POI2017]Turysta

    4727: [POI2017]Turysta Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 117  Solved ...

  4. BZOJ.4727.[POI2017]Turysta(哈密顿路径/回路 竞赛图)

    题目链接 \(Description\) 给出一个n个点的有向图,任意两个点之间有且仅一条有向边.对于每个点v,求出从v出发的一条经过点数最多,且没有重复经过同一个点一次以上的简单路径. n<= ...

  5. HDU3414 Tour Route(竞赛图寻找哈密顿回路)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=3414 本文链接:http://www.cnblogs.com/Ash-ly/p/5459540.html ...

  6. 图论 竞赛图(tournament)学习笔记

    竞赛图(tournament)学习笔记 现在只是知道几个简单的性质... 竞赛图也叫有向完全图. 其实就是无向完全图的边有了方向. ​ 有一个很有趣的性质就是:一个tournament要么没有环,如果 ...

  7. POJ1776(哈密顿路径)

    题目: http://poj.org/problem?id=1776 题意: 给出一个n*n的矩阵,若第i个任务做完之后可以做第j个任务,则矩阵的第i行第j列为1,否则为0.机器完成一项任务之后会自动 ...

  8. BZOJ 4726: [POI2017]Sabota?

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 301  Solved ...

  9. 玩转SQL Server复制回路の变更数据类型、未分区表转为分区表

    玩转SQL Server复制回路の变更数据类型.未分区表转为分区表 复制的应用: 初级应用:读写分离.数据库备份 高级应用:搬迁大型数据库(跨机房).变更数据类型.未分区表转为分区表 京东的复制专家 ...

随机推荐

  1. Shuffle Bags让你的随机不那么随机

    前言 当我最初写游戏时,我经常使用标准Random()函数,然后写一堆if和else条件来我获得预期结果.如果结果不太好,我会写更多的条件进行过滤或者筛选,直到我觉得游戏变得有趣.最近我发现有更好的方 ...

  2. keyup在移动端失效解决方法

    keyup在移动端失效解决方法: $("#OBJ").on("input propertychange", function(){ }); 采用 input 与 ...

  3. 图片人脸检测(OpenCV版)

    图片人脸检测 人脸检测使用到的技术是OpenCV,上一节已经介绍了OpenCV的环境安装,点击查看. 功能展示 识别一种图上的所有人的脸,并且标出人脸的位置,画出人眼以及嘴的位置,展示效果图如下: 多 ...

  4. 转载----C/C++ 中 const 修饰符用法总结

    感谢原创作者,写的好详细.不忍错过,所以转载过来了... 原文地址: https://www.cnblogs.com/icemoon1987/p/3320326.html 在这篇文章中,我总结了一些C ...

  5. Python基础_异常处理与跟踪

    异常的种类 AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常:基本上是无法打开文件 ImportError 无法引入模块或 ...

  6. First scrum meeting report - 151017

    提要 今天开会主要是讨论一下北航MOOC客户端的具体要求和每个人的大致分工.会议后来还简单商讨了一下我们app的大致界面框架. 会议地点:大运村KFC 会议时间:2015年10月17日,15:00-1 ...

  7. [BUAA OO]第二次博客作业

    第五次作业 这次作业是电梯系列作业的终极版,要求是使用多线程实现三部电梯的运行.这次作业的难点在于第一次运用多线程技术,对于线程中的行为并不了解,以及电梯功能的实现(如果之前作业采取的是扫描指令队列预 ...

  8. Oracle安装后出现的问题

    安装oracle没有勾选"安装模板数据库",可以通过执行以下命令进行修改: cd $ORACLE_HOME/rdbms/admin 到这个目录下sqlplus /as sysdba ...

  9. 进阶系列(10)—— C#元数据和动态编程

    一.元数据的介绍 元数据是用来描述数据的数据(Data that describes other data).单单这样说,不太好理解,我来举个例子.下面是契诃夫的小说<套中人>中的一段,描 ...

  10. mvc 路由配置-学习

    MapRoute(RouteCollection, String, String) 映射指定的URL路由. 'Declaration <ExtensionAttribute> _ Publ ...