\(\mathcal{Description}\)

  Link.

  给定一个 \(n\) 个点 \(m\) 条边的无向图,在其上找到一条包括不少于 \(\lceil\frac{n}2\rceil\) 个结点的简单路径;或者将至少 \(\lceil\frac{n}2\rceil\) 个结点划分为若干二元组,使得任意两个不同二元组内四个结点的导出子图含有至多两条边。多组数据。

  \(n,\sum n\le5\times10^5\),\(m,\sum m\le10^6\)。

\(\mathcal{Solution}\)

  去分开刚两个 NP 问题,请。

  这种给两个问题让你解其中一个的,显然以尝试求解一个失败为条件来求解另一个,不可能分开解的。比如本题,随便选一个起点 DFS 全图,若发现深度不小于 \(\lceil\frac{n}2\rceil\) 的 DFS 树上结点,回答第一问,结束。否则,问题转化为:一个图的 DFS 满足树深 \(<\lceil\frac{n}2\rceil\),求解第二问。

  由于 DFS 树没有横叉边,所以在树上某一结点的左子树选一个,右子树选一个来组成一对,这两对间的导出子图显然不超过两条边。所以用 std::vector 记录子树内匹配剩下的结点,在父亲处与兄弟子树剩下的结点配对即可。可以证明在树深 \(<\lceil\frac{n}2\rceil\) 的情况下一定有解。

  复杂度 \(\mathcal O(\sum n+m)\)。

\(\mathcal{Code}\)

/* Clearink */

#include <cstdio>
#include <vector>
#include <cstdlib>
#include <assert.h> inline int rint () {
int x = 0, f = 1; char s = getchar ();
for ( ; s < '0' || '9' < s; s = getchar () ) f = s == '-' ? -f : f;
for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
return x * f;
} template<typename Tp>
inline void wint ( Tp x ) {
if ( x < 0 ) putchar ( '-' ), x = ~ x + 1;
if ( 9 < x ) wint ( x / 10 );
putchar ( x % 10 ^ '0' );
} const int MAXN = 5e5, MAXM = 1e6;
int n, m, ecnt, head[MAXN + 5], p[MAXN + 5];
bool vis[MAXN + 5], solved;
std::vector<int> path, rest[MAXN + 5];
std::vector<std::pair<int, int> > pairs; struct Edge { int to, nxt; } graph[MAXM * 2 + 5]; inline void link ( const int s, const int t ) {
graph[++ ecnt] = { t, head[s] };
head[s] = ecnt;
} inline void clear () {
ecnt = solved = 0, path.clear (), pairs.clear ();
for ( int i = 1; i <= n; ++ i ) head[i] = vis[i] = 0, rest[i].clear ();
} inline void printPath () {
solved = true;
printf ( "PATH\n%d", ( int ) path.size () );
for ( int i = 0; i ^ path.size (); ++ i ) {
printf ( "%c%d", i ? ' ' : '\n', path[i] );
}
putchar ( '\n' );
} inline void printPairs () {
solved = true;
printf ( "PAIRING\n%d\n", ( int ) pairs.size () );
for ( auto p: pairs ) printf ( "%d %d\n", p.first, p.second );
} inline void solve ( const int u ) {
if ( solved ) return ;
vis[u] = true, path.push_back ( u ), p[u] = u;
if ( ( int ) path.size () << 1 >= n ) printPath ();
for ( int i = head[u], v; i; i = graph[i].nxt ) {
if ( !vis[v = graph[i].to] ) {
solve ( v ), path.pop_back ();
if ( solved ) return ;
while ( !rest[p[u]].empty () && !rest[p[v]].empty () ) {
pairs.push_back ( { rest[p[u]].back (), rest[p[v]].back () } );
if ( ( int ) pairs.size () << 2 >= n ) return printPairs ();
rest[p[u]].pop_back (), rest[p[v]].pop_back ();
}
p[u] = rest[p[u]].empty () ? p[v] : p[u];
}
}
rest[p[u]].push_back ( u );
} int main () {
for ( int T = rint (); T --; ) {
n = rint (), m = rint (), clear ();
for ( int i = 1, u, v; i <= m; ++ i ) {
u = rint (), v = rint ();
link ( u, v ), link ( v, u );
}
solve ( 1 );
assert ( solved );
}
return 0;
}

\(\mathcal{Details}\)

  std::vector 的操作能少压入就少压入啊……不知道怎么内存就挂掉了。

Solution -「CF 1391E」Pairs of Pairs的更多相关文章

  1. Solution -「CF 923F」Public Service

    \(\mathscr{Description}\)   Link.   给定两棵含 \(n\) 个结点的树 \(T_1=(V_1,E_1),T_2=(V_2,E_2)\),求一个双射 \(\varph ...

  2. Solution -「CF 1342E」Placing Rooks

    \(\mathcal{Description}\)   Link.   在一个 \(n\times n\) 的国际象棋棋盘上摆 \(n\) 个车,求满足: 所有格子都可以被攻击到. 恰好存在 \(k\ ...

  3. Solution -「CF 1622F」Quadratic Set

    \(\mathscr{Description}\)   Link.   求 \(S\subseteq\{1,2,\dots,n\}\),使得 \(\prod_{i\in S}i\) 是完全平方数,并最 ...

  4. Solution -「CF 923E」Perpetual Subtraction

    \(\mathcal{Description}\)   Link.   有一个整数 \(x\in[0,n]\),初始时以 \(p_i\) 的概率取值 \(i\).进行 \(m\) 轮变换,每次均匀随机 ...

  5. Solution -「CF 1586F」Defender of Childhood Dreams

    \(\mathcal{Description}\)   Link.   定义有向图 \(G=(V,E)\),\(|V|=n\),\(\lang u,v\rang \in E \Leftrightarr ...

  6. Solution -「CF 1237E」Balanced Binary Search Trees

    \(\mathcal{Description}\)   Link.   定义棵点权为 \(1\sim n\) 的二叉搜索树 \(T\) 是 好树,当且仅当: 除去最深的所有叶子后,\(T\) 是满的: ...

  7. Solution -「CF 623E」Transforming Sequence

    题目 题意简述   link.   有一个 \(n\) 个元素的集合,你需要进行 \(m\) 次操作.每次操作选择集合的一个非空子集,要求该集合不是已选集合的并的子集.求操作的方案数,对 \(10^9 ...

  8. Solution -「CF 1023F」Mobile Phone Network

    \(\mathcal{Description}\)   Link.   有一个 \(n\) 个结点的图,并给定 \(m_1\) 条无向带权黑边,\(m_2\) 条无向无权白边.你需要为每条白边指定边权 ...

  9. Solution -「CF 599E」Sandy and Nuts

    \(\mathcal{Description}\)   Link.   指定一棵大小为 \(n\),以 \(1\) 为根的有根树的 \(m\) 对邻接关系与 \(q\) 组 \(\text{LCA}\ ...

随机推荐

  1. $.ajax传输js数组,spring接收异常

    今天测试,出现一个奇怪的问题 $.ajax传输js数组,spring接收这个数组,出现奇怪的现象,如果数组只有一个元素,且这个元素字符串最后一个字符是以逗号,结尾的话, spring会自动把这个逗号去 ...

  2. mongodb基础整理篇————简单介绍[一]

    前言 简单介绍一下文档数据库. 正文 mongodb 是一个以json为数据模型的文档数据库. 这里要介绍一下什么是json.因为有些人认为'{a:1,b:2}' 是json,而"this ...

  3. Hystrix的原理与架构

    一.定义 一个开源的延迟与容错框架,用于隔离访问远程服务.第三记库,防止出现级联失败 当某个或某些服务反应慢或者超时严重,主动熔断,当情况好转后,可以自动重连 策略:服务降级.服务限流.服务熔断.服务 ...

  4. 通过暗码去打开/关闭usb debug开关

    通过暗码去打开/关闭usb debug开关 通过暗码去打开/关闭usb debug开关1. Description2. Analysis3. Solution4. Summary 1. Descrip ...

  5. 微服务架构 | 3.3 Apache Zookeeper 注册中心

    @ 目录 前言 1. Zookeeper 基础知识 1.1 Zookeeper 是什么 1.2 Zookeeper 的数据结构 1.3 Watcher 机制 1.4 常见应用场景分析 1.5 Zook ...

  6. leetcode刷题目录

    leetcode刷题目录 1. 两数之和 2. 两数相加 3. 无重复字符的最长子串 4. 寻找两个有序数组的中位数 5. 最长回文子串 6. Z 字形变换 7. 整数反转 8. 字符串转换整数 (a ...

  7. 2月3日 体温APP开发记录

    1.阅读构建之法 现代软件工程(第三版) 2.观看Android开发视频教程最新版 Android Studio开发 3.回返地址学习,下载导入相关jar包

  8. 【C++】自定义数据类型

    自定义数据类型 标签:c++ 目录 自定义数据类型 一.结构体 定义方法: 特点: 成员访问方式: 初始化: 结构数组 指针和动态内存分配: 结构变量作为函数参数: 二.联合 定义方法: 特点: 举例 ...

  9. 小程序或者vue,解决菜单导航做做成轮播的样子

    案例: 其中最重要的思路就是如何让第二次或第三次以及后面的轮播有数据: 做法大致跟轮播图做法一样,只不过我们需要进行书写样式,代码如下: <!-- 做一个轮播图navbar demo --> ...

  10. elasticsearch算法之词项相似度算法(二)

    六.莱文斯坦编辑距离 前边的几种距离计算方法都是针对相同长度的词项,莱文斯坦编辑距离可以计算两个长度不同的单词之间的距离:莱文斯坦编辑距离是通过添加.删除.或者将一个字符替换为另外一个字符所需的最小编 ...