Solution -「LOCAL」割海成路之日
\(\mathcal{Description}\)
给定 \(n\) 个点的一棵树,有 \(1,2,3\) 三种边权。一条简单有向路径 \((s,t)\) 合法,当且仅当走过一条权为 \(3\) 的边之后,只通过了权为 \(1\) 的边。\(m\) 次询问,每次询问给定 \(a,b,s,t\),表示将边 \((a,b)\) 的权 \(-1\)(若权已为 \(1\) 则不变),并询问 \(t\) 是否能走到 \(s\);有多少点能够走到 \(s\)。
\(n,m\le 3 \times 10^5\)。
\(\mathcal{Solution}\)
由于是求多少点可达 \(s\),考虑把路径的规则反过来:一开始只能走权为 \(1\) 的边,放一次“大招”(走过权为 \(3\) 的边)后就能任意走,但只能开一次大。问题变成求 \(s\) 是否可达 \(t\),\(s\) 可达多少点。
显然,\(s\) 可达的点可以归为如下几类:
与 \(s\) 在同一个 \(1-\)联通块。
处于一个 \(12-\)联通块,且该联通块由权为 \(3\) 的边与 \(s\) 所在的 \(1-\)联通块相连。
考虑用并查集维护 \(1-\)联通块和 \(12-\)联通块。第一类点直接求 size 就可以了。第二类点,用每一个 \(12-\)联通块的根向父亲贡献,最后加上父亲对当前块的贡献即为答案。
\(\mathcal{Code}\)
/* Clearink */
#include <cstdio>
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 = 3e5;
int n, m, ecnt = 1, head[MAXN + 5], fa[MAXN + 5], facol[MAXN + 5], rchs[MAXN + 5];
struct Edge { int to, cst, nxt; } graph[MAXN * 2 + 5];
inline void link ( const int s, const int t, const int c ) {
graph[++ ecnt] = { t, c, head[s] };
head[s] = ecnt;
}
struct DSU {
int fa[MAXN + 5], siz[MAXN + 5];
inline int operator () ( const int k ) { return find ( k ); }
inline int operator [] ( const int k ) const { return siz[k]; }
inline void init () {
for ( int i = 1; i <= n; ++ i ) {
fa[i] = i, siz[i] = 1;
}
}
inline int find ( const int x ) { return x ^ fa[x] ? fa[x] = find ( fa[x] ) : x; }
inline bool unite ( int x, int y ) {
if ( ( x = find ( x ) ) == ( y = find ( y ) ) ) return false;
return siz[fa[x] = y] += siz[x], true;
}
} dsu[2];
inline void init ( const int u ) {
for ( int i = head[u], v; i; i = graph[i].nxt ) {
if ( ( v = graph[i].to ) ^ fa[u] ) {
fa[v] = u, facol[v] = graph[i].cst;
init ( v );
}
}
}
int main () {
freopen ( "sea.in", "r", stdin );
freopen ( "sea.out", "w", stdout );
n = rint (), m = rint ();
for ( int i = 1, u, v, c; i < n; ++ i ) {
u = rint (), v = rint (), c = rint ();
link ( u, v, c ), link ( v, u, c );
}
dsu[0].init (), dsu[1].init (), init ( 1 );
for ( int i = 2; i <= n; ++ i ) {
if ( facol[i] <= 2 ) dsu[1].unite ( i, fa[i] );
if ( facol[i] <= 1 ) dsu[0].unite ( i, fa[i] );
}
for ( int i = 2; i <= n; ++ i ) {
if ( facol[i] == 3 ) {
rchs[dsu[0]( fa[i] )] += dsu[1][i];
}
}
for ( int a, b, s, t; m --; ) {
a = rint (), b = rint (), s = rint (), t = rint ();
if ( fa[a] == b ) a ^= b ^= a ^= b;
if ( facol[b] == 3 ) {
-- facol[b];
rchs[dsu[0]( a )] -= dsu[1][b];
rchs[dsu[0]( fa[dsu[1]( a )] )] += dsu[1][b];
dsu[1].unite ( b, a );
} else if ( facol[b] == 2 ) {
-- facol[b];
rchs[dsu[0]( a )] += rchs[b];
dsu[0].unite ( b, a );
}
putchar ( dsu[1]( s ) == dsu[1]( t )
|| dsu[0]( fa[dsu[1]( t )] ) == dsu[0]( s )
|| dsu[1]( fa[dsu[0]( s )] ) == dsu[1]( t ) ?
'1' : '0' ), putchar ( ' ' );
wint ( dsu[1][dsu[1]( s )] + rchs[dsu[0]( s )]
+ ( facol[dsu[0]( s )] == 3 ? dsu[1][dsu[1]( fa[dsu[0]( s )] )] : 0 ) );
putchar ( '\n' );
}
return 0;
}
\(\mathcal{Details}\)
考试的时候拿阳寿去肝 T2,压根没发现这题水得多 qwqwq。
Solution -「LOCAL」割海成路之日的更多相关文章
- lfyzoj103 割海成路之日
问题描述 现在,摆在早苗面前的是一道简单题.只要解决了这道简单题,早苗就可以发动她现人神的能力了: 输出 \[1\ \mathrm{xor}\ 2\ \mathrm{xor} \cdots \math ...
- NOIP 模拟 $28\; \rm 割海成路之日$
题解 \(by\;zj\varphi\) 用两个集合分别表示 \(1\) 边联通块,\(1,2\) 边联通块 . \(\rm son_x\) 表示当前节点通过 \(3\) 类边能到的 \(2\) 联通 ...
- Solution -「LOCAL」大括号树
\(\mathcal{Description}\) OurTeam & OurOJ. 给定一棵 \(n\) 个顶点的树,每个顶点标有字符 ( 或 ).将从 \(u\) 到 \(v\) ...
- Solution -「LOCAL」Drainage System
\(\mathcal{Description}\) 合并果子,初始果子的权值在 \(1\sim n\) 之间,权值为 \(i\) 的有 \(a_i\) 个.每次可以挑 \(x\in[L,R]\) ...
- Solution -「LOCAL」Burning Flowers
灼之花好评,条条生日快乐(假装现在 8.15)! \(\mathcal{Description}\) 给定一棵以 \(1\) 为根的树,第 \(i\) 个结点有颜色 \(c_i\) 和光亮值 ...
- Solution -「LOCAL」舟游
\(\mathcal{Description}\) \(n\) 中卡牌,每种三张.对于一次 \(m\) 连抽,前 \(m-1\) 次抽到第 \(i\) 种的概率是 \(p_i\),第 \(m\) ...
- Solution -「LOCAL」解析电车
\(\mathcal{Description}\) 给定 \(n\) 个点 \(m\) 条边的无向图,每条边形如 \((u,v,r)\),表示 \(u,v\) 之间有一条阻值为 \(r\Omega ...
- Solution -「LOCAL」二进制的世界
\(\mathcal{Description}\) OurOJ. 给定序列 \(\{a_n\}\) 和一个二元运算 \(\operatorname{op}\in\{\operatorname{ ...
- Solution -「LOCAL」过河
\(\mathcal{Description}\) 一段坐标轴 \([0,L]\),从 \(0\) 出发,每次可以 \(+a\) 或 \(-b\),但不能越出 \([0,L]\).求可达的整点数. ...
随机推荐
- 使用yum安装php*时报错的解决办法
# yum -y install php* 注意: php53-odbc64-5.3.3-2.el5.x86_64 from base has depsolving problems --> ...
- vue2.0组件库
UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基于Vue和WeUI的组件库 mint-ui - Vue 2的移动UI元素 iview - 基于 Vuejs 的开 ...
- PAT 乙级 1001. 害死人不偿命的(3n+1)猜想 (15)(C语言描述)
卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半.这样一直反复砍下去,最后一定在某一步得到n=1.卡拉兹在1950年的世界数 ...
- 网络协议学习笔记(二)物理层到MAC层,交换机和VLAN,ICMP与ping原理
概述 之前网络学习笔记主要讲解了IP的诞生,或者说整个操作系统的诞生,一旦有了IP,就可以在网络的环境里和其他的机器展开沟通了.现在开始给大家讲解关于网络底层的相关知识. 从物理层到MAC层:如何在宿 ...
- python分支结构与循环结构
python分支结构 一.if 单条件形式 # 年轻人的世界都不容易 age > 18 age = int(input("请输入您的年龄:")) # input()函数 模拟 ...
- Nginx 反向代理解决跨域问题分析
当你遇到跨域问题,不要立刻就选择复制去尝试.请详细看完这篇文章再处理 .我相信它能帮到你. 分析前准备: 前端网站地址:http://localhost:8080 服务端网址:http://local ...
- 【记录一个问题】opencv + cuda编译release版本后,链接出现奇怪的符号
链接出现以下信息: 1 /home/admin/opencv/20190610_cuda_release/lib64/libopencv_core.a(ocl.cpp.o): In function ...
- java有四种访问权限
Java面向对象的封装性是通过对成员变量和方法进行访问控制实现的,访问控制分为4个等级:私有.默认.保护和公有,具体规则如下表:
- linux中awk命令(最全面秒懂)
目录 一:linux中awk命令 1.awk命令简介 2.awk作用 3.awk的语法格式 4.解析awk使用方法 5.参数 6.awk的生命周期 二:awk中的预定义变量 三:awk运行处理规则的执 ...
- LeetCode650
LeetCode每日一题2021.9.19 跳转链接 分析 我们发现每个数字只能由它的因数通过复制而来, 因为复制操作是每次去添加一个相同的个数. 因此我们就可以得出DP方程 dp[i] = min( ...