[CF1007D]Ants[2-SAT+树剖+线段树优化建图]
题意
我们用路径 \((u, v)\) 表示一棵树上从结点 \(u\) 到结点 \(v\) 的最短路径。
给定一棵由 \(n\) 个结点构成的树。你需要用 \(m\) 种不同的颜色为这棵树的树边染色,在这 \(m\) 种颜色中,第 \(i\) 种颜色有两条备选路径
\((a_i, b_i)\) 与 \((c_i, d_i)\),你的任务是判断是否存在一种合法的染色方案,使得每种颜色 \(i\) 所对应的两条备选路径中都有至少一条满足:
该路径上的所有树边的颜色均为颜色 \(i\)。若存在,输出 YES,并依次输出每种颜色所对应的两条备选路径中,哪一条是满足要求的。
若输出 1,则表示路径 \((a_i, b_i)\) 是合法的,若输出 2,则表示路径 \((c_i, d_i)\) 是合法的);若不存在,输出 NO。
\(2 \leq n \leq 10^5, 1 \leq m \leq 10^4, 1 \leq a_i, b_i, c_i, d_i \leq n, a_i \neq b_i, c_i \neq b_i\)。
分析
令一种颜色的两条路径互为逆命题。(如果两条边可以同时出现只出现一条一定可以满足)
考虑一种暴力的做法:枚举经过一条边的所有路径,命题两两连边,这个过程可以前缀优化建图,但似乎还不够优秀。
能不能更高效地将一条路径的影响记录到树上呢?容易联想到树剖,我们用树剖+线段树的方式将路径的影响加入线段树中 \({log}^2\) 个节点中并标记永久化,对线段树上每个节点的所有路径前缀优化建图。
容易发现每个点(线段树上)的限制不仅来自当前节点,他的所有祖先和子树内的路径与他之间都只能选一个,所以节点的最后一个命题向两个儿子节点的第一个命题连边构成树形结构,就满足了每个点的限制。
空间复杂度 \(O(m{log}^2n)\) ,时间复杂度 \(O(m{log}^2n)\)。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define go(i, u, v) for(int (i) = head[(u)], (v) = e[(i)].to; (i); (i)=e[(i)].lst, (v)=e[(i)].to)
#define rep(i, a, b) for(int (i) = (a); (i) <= (b); ++(i))
#define pb push_back
inline int gi() {
int x = 0,f = 1;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') f = -1;
ch = getchar();
}
while(isdigit(ch)) {
x = (x << 3) + (x << 1) + ch - 48;
ch = getchar();
}
return x * f;
}
template <typename T> inline void Max(T &a, T b){if(a < b) a = b;}
template <typename T> inline void Min(T &a, T b){if(a > b) a = b;}
const int N = 1e5 + 7, Nd = 6e6 + 7;
int n, edc;
int head[N], ndc;
struct edge {
int lst, to;
edge(){}edge(int lst, int to):lst(lst), to(to){}
}e[N << 1];
void Add(int a, int b) {
e[++edc] = edge(head[a], b), head[a] = edc;
e[++edc] = edge(head[b], a), head[b] = edc;
}
vector<int> G[Nd];
void lim(int a, int b) {
G[a].pb(b), G[b ^ 1].pb(a ^ 1);
}
int fa[N], in[N], dep[N], top[N], son[N], zson[N], tim;
void dfs1(int u) {
son[u] = 1;
go(i, u, v)if(v ^ fa[u]) {
dep[v] = dep[u] + 1, fa[v] = u;
dfs1(v);
son[u] += son[v];
if(son[v] > son[zson[u]]) zson[u] = v;
}
}
void dfs2(int u, int from) {
top[u] = from, in[u] = ++tim;
if(zson[u]) dfs2(zson[u], from);
go(i, u, v)if(v ^ fa[u] && v ^ zson[u]) dfs2(v, v);
}
vector<int> path[N << 2];
int L[N << 2], R[N << 2];
#define Ls o << 1
#define Rs o << 1 | 1
void modify(int L, int R, int l, int r, int o, int id) {
if(L <= l && r <= R) { path[o].pb(id); return; }
int mid = l + r >> 1;
if(L <= mid) modify(L, R, l, mid, Ls, id);
if(R > mid) modify(L, R, mid + 1, r, Rs, id);
}
void build(int l, int r, int o) {
L[o] = ++ndc, ndc += path[o].size(), R[o] = ndc;
if(o > 1) {
lim(L[o] << 1 | 1, R[o >> 1] << 1 | 1);
if(!path[o].empty()) {
int x = path[o][0];
lim(R[o >> 1] << 1, x ^ 1);
}
}
for(int i = 0; i < path[o].size(); ++i) {
int x = path[o][i];
lim(L[o] + i << 1 | 1, x ^ 1);
lim(L[o] + i + 1 << 1 | 1, L[o] + i << 1 | 1);
if(i ^ 0) lim(L[o] + i - 1 << 1, x ^ 1);
}
if(l == r) return;
int mid = l + r >> 1;
build(l, mid, Ls);
build(mid + 1, r, Rs);
}
void ins(int x, int y, int id) {
for(; top[x] ^ top[y]; y = fa[top[y]]) {
if(dep[top[x]] > dep[top[y]]) swap(x, y);
modify(in[top[y]], in[y], 1, n, 1, id);
}
if(dep[x] > dep[y]) swap(x, y);
if(x ^ y) modify(in[x] + 1, in[y], 1, n, 1, id);
}
int low[Nd], pre[Nd], st[Nd], scc[Nd], scc_cnt, tp;
void tarjan(int u) {
low[u] = pre[u] = ++tim;st[++ tp] = u;
for(auto v : G[u]) {
if(!low[v]) {
tarjan(v);
Min(pre[u], pre[v]);
}else if(!scc[v]) Min(pre[u], low[v]);
}
if(low[u] == pre[u] && ++scc_cnt)
for(int x = -1; x ^ u;)
scc[x = st[tp--]] = scc_cnt;
}
int main() {
n = gi();ndc = n;
rep(i, 1, n - 1) Add(gi(), gi());
dep[1] = 1, dfs1(1), dfs2(1, 1);
int m = gi();
rep(i, 1, m) {
int a = gi(), b = gi(), c = gi(), d = gi();
ins(a, b, i << 1);
ins(c, d, i << 1 | 1);
}
build(1, n, 1);
tim = 0;
for(int i = 1; i <= ndc * 2 + 1; ++i) if(!scc[i]) tarjan(i);
rep(i, 1, m) {
if(scc[i << 1] == scc[i << 1 | 1]) return puts("NO"), 0;
}
puts("YES");
rep(i, 1, m) {
puts(scc[i << 1] < scc[i << 1 | 1] ? "1" : "2");
}
return 0;
}
[CF1007D]Ants[2-SAT+树剖+线段树优化建图]的更多相关文章
- BZOJ_2238_Mst_树剖+线段树
BZOJ_2238_Mst_树剖+线段树 Description 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影 ...
- BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树
BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树 Description 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为 ...
- BZOJ_2157_旅游_树剖+线段树
BZOJ_2157_旅游_树剖+线段树 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但 ...
- 【BZOJ5210】最大连通子块和 树剖线段树+动态DP
[BZOJ5210]最大连通子块和 Description 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块 ...
- [LNOI2014]LCA(树剖+线段树)
\(\%\%\% Fading\) 此题是他第一道黑题(我的第一道黑题是蒲公英) 一直不敢开,后来发现是差分一下,将询问离线,树剖+线段树维护即可 \(Code\ Below:\) #include ...
- LOJ#3088. 「GXOI / GZOI2019」旧词(树剖+线段树)
题面 传送门 题解 先考虑\(k=1\)的情况,我们可以离线处理,从小到大对于每一个\(i\),令\(1\)到\(i\)的路径上每个节点权值增加\(1\),然后对于所有\(x=i\)的询问查一下\(y ...
- BZOJ3531-[Sdoi2014]旅行(树剖+线段树动态开点)
传送门 完了今天才知道原来线段树的动态开点和主席树是不一样的啊 我们先考虑没有宗教信仰的限制,那么就是一个很明显的树剖+线段树,路径查询最大值以及路径和 然后有了宗教信仰的限制该怎么做呢? 先考虑暴力 ...
- 【bzoj4699】树上的最短路(树剖+线段树优化建图)
题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...
- POJ3237 Tree(树剖+线段树+lazy标记)
You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbe ...
随机推荐
- Git 命令快速浏览
Git 命令快速浏览 创建 Git 可管理的仓库 git init 查看当前仓库的状态 git status 添加到仓库,实际上是添加到暂存区 git add [-A | --all] git add ...
- 解决VS调试Web应用无问题而部署在IIS上报500和403的问题
[问题:报500]不能在此路径中使用此配置节.如果在父级别上锁定了该节,便会出现这种情况.锁定是默认设置的(overrideModeDefault="Deny" [解决方案] 运行 ...
- 小慢歌之基于RHEL8/CentOS8的网络IP配置详解
➡ 在rhel8(含centos8)上,没有传统的network.service,在/etc/sysconfig/network-scripts/里也看不到任何脚本文件,那么该如何进行网络配置呢. ➡ ...
- 判断Exception类中是否有InnerException属性
public static class ExceptionExtend { /// <summary> /// 利用反射来判断对象是否包含某个属性 /// </summary> ...
- http的断点续传
要实现断点续传的功能,通常都需要客户端记录下当前的下载进度,并在需要续传的时候通知服务端本次需要下载的内容片段. HTTP1.1协议(RFC2616)中定义了断点续传相关的HTTP头 Range和Co ...
- orcl regexp_like 的用法
oracle10g以上支持正则表达式的函数主要有下面四个:1.REGEXP_LIKE :与LIKE的功能相似2.REGEXP_INSTR :与INSTR的功能相似3.REGEXP_SUBSTR :与S ...
- 微信小程序里解决app.js onLaunch事件与小程序页面的onLoad加载前后异常问题
使用 Promise 解决小程序页面因为需要app.js onLaunch 参数导致的请求失败 app.js onLaunch 的代码 "use strict"; Object.d ...
- 【转】Java学习---垃圾回收算法与 JVM 垃圾回收器综述
[原文]https://www.toutiao.com/i6593931841462338062/ 垃圾回收算法与 JVM 垃圾回收器综述 我们常说的垃圾回收算法可以分为两部分:对象的查找算法与真正的 ...
- Django有关的所有命令
1. Django的安装 pip install django ==1.11.11 pip install -i yuan django==1.11.11 2. 创建项目 django-admin s ...
- OpenCV学习参考 即时贴
注意:本博文在github上日常更新(保持GitHub最新) https://github.com/SylvesterLi/MyOpenCVCode 基本安装:https://blog.csdn.ne ...