当前位置: 首页 > wzjs >正文

html5结构的网站郑州推广优化公司

html5结构的网站,郑州推广优化公司,今日国际新闻最新消息事件,全国黄页平台题目描述 小杨有一棵包含 $ n $ 个节点的树,其中节点的编号从 1 到 $ n $。 小杨设置了一个好点对 { ⟨ u 1 , v 1 ⟩ , ⟨ u 2 , v 2 ⟩ , … , ⟨ u a , v a ⟩ } \{\langle u_1, v_1 \rangle, \langle u_2, v_2 \rangle, \dots, \langle u_a, v_a \rangle\} {…

题目描述

小杨有一棵包含 $ n $ 个节点的树,其中节点的编号从 1 到 $ n $。

小杨设置了一个好点对 { ⟨ u 1 , v 1 ⟩ , ⟨ u 2 , v 2 ⟩ , … , ⟨ u a , v a ⟩ } \{\langle u_1, v_1 \rangle, \langle u_2, v_2 \rangle, \dots, \langle u_a, v_a \rangle\} {⟨u1,v1,u2,v2,,ua,va⟩} 和一个坏点对 ⟨ b u , b v ⟩ \langle b_u, b_v \rangle bu,bv。一个节点能被删除,当且仅当:

  • 删除该节点后对于所有的 $ 1 \leq i \leq a $,好点对 $ u_i $ 和 $ v_i $ 仍然连通;
  • 删除该节点后坏点对 $ b_u $ 和 $ b_v $ 不连通。

如果点对中的任意一个节点被删除,其视为不连通。

小杨想知道,还有多少个节点能被删除。

输入格式

第一行包含两个非负整数 $ n $, $ a $,含义如下题面所示。

接下来 n − 1 n - 1 n1 行,每行包含两个正整数 $ x_i, y_i $,代表存在一条连接节点 $ x_i $ 和 $ y_i $ 的边;

之后 $ a $ 行,每行包含两个正整数 $ u_i, v_i $,代表一个好点对 $ \langle u_i, v_i \rangle $;

最后一行包含两个正整数 $ b_u, b_v $,代表坏点对 $ \langle b_u, b_v \rangle $。

输出格式

输出一个非负整数,代表删除的节点个数。

输入输出样例 #1

输入 #1

6 2
1 3
1 5
3 6
3 2
5 4
5 4
5 3
2 6

输出 #1

2

说明/提示

子任务编号分值$ n $$ a $
1 20 20 20 = 10 =10 =10 = 0 =0 =0
2 20 20 20$ \leq 100 $$ \leq 100 $
3 60 60 60$ \leq 10^6 $$ \leq 10^5 $

对于全部数据,保证有 $ 1 \leq n \leq 10^6 $, $ 0 \leq a \leq 10^5 $, $ u_i \neq v_i $, $ b_u \neq b_v $。

solution

如果 u ,v 的路径上的一点被删除,则 u, v 不联通,所以被删除的点应该满足两个条件

  • 在坏点对点路径上
  • 不在任何好点对的路径上
    所以可以遍历坏点对路径上的每一点,如果它不在任何好点对上则满足条件。可以结合最近公共祖先完成判断。

代码

#include <iostream>
#include "bit"
#include "vector"
#include "unordered_set"
#include "unordered_map"
#include "set"
#include "queue"
#include "algorithm"
#include "bitset"
#include "cstring"
#include "cmath"using namespace std;const int N = 1e6 + 1, M = 1e5 + 1;
int n, a, U[M], V[M], s, t, f[N][21], d[N];
vector<int> e[N];void dfs(int u, int p) {d[u] = d[p] + 1;f[u][0] = p;for (int i = 1; i <= 20; i++) f[u][i] = f[f[u][i - 1]][i - 1];for (int v: e[u]) {if (v != p) {dfs(v, u);}}
}int lca(int x, int y) {if (x == y) return x;if (d[x] < d[y]) swap(x, y);for (int i = 20; d[x] > d[y]; i--) {if (d[f[x][i]] >= d[y])x = f[x][i];}if (x == y) return x;for (int i = 20; i >= 0; i--) {if (f[x][i] != f[y][i])x = f[x][i], y = f[y][i];}return f[x][0];
}int main() {scanf("%d %d", &n, &a);for (int i = 1; i < n; i++) {int x, y;scanf("%d %d", &x, &y);e[x].push_back(y);e[y].push_back(x);}for (int i = 1; i <= a; i++) scanf("%d %d", &U[i], &V[i]);scanf("%d %d", &s, &t);dfs(1, 0);int p = lca(s, t);int cnt = 0;for (; s != p; s = f[s][0]) {int tt = 1;for(int i = 1; i <= a; i++){int P =  lca(U[i], V[i]);if(lca(P, s) == P && (lca(s, U[i]) == s || lca(s, V[i]) == s)){tt = 0;break;}}cnt += tt;}for (; ; t = f[t][0]) {int tt = 1;for(int i = 1; i <= a; i++){int P =  lca(U[i], V[i]);if(lca(P, t) == P && (lca(t, U[i]) == t || lca(t, V[i]) == t)){tt = 0;break;}}cnt += tt;if(t == p) break;}cout << cnt;
}
  • 用 dfn 序求最近公共祖先,可以将对数级别降低到常数级别。
#include <iostream>
#include "bit"
#include "vector"
#include "unordered_set"
#include "unordered_map"
#include "set"
#include "queue"
#include "algorithm"
#include "bitset"
#include "cstring"
#include "cmath"using namespace std;const int N = 1e6 + 1, M = 1e5 + 1;
int n, a, U[M], V[M], s, t, f[N][21], id, dfn[N];
vector<int> e[N];void dfs(int u, int p) {f[dfn[u] = ++id][0] = p;for (int v: e[u]) {if (v != p) {dfs(v, u);}}
}inline int my_min(int x, int y){return dfn[x] < dfn[y] ? x : y;
}int lca(int x, int y) {if (x == y) return x;x = dfn[x], y = dfn[y];if (x > y) swap(x, y);int d = (int)log2(y - x);x++;// 求 x y 之间 dfn 最小的那个数return my_min(f[x][d], f[y - (1 << d) + 1][d]);
}int main() {scanf("%d %d", &n, &a);for (int i = 1; i < n; i++) {int x, y;scanf("%d %d", &x, &y);e[x].push_back(y);e[y].push_back(x);}for (int i = 1; i <= a; i++) scanf("%d %d", &U[i], &V[i]);scanf("%d %d", &s, &t);dfs(1, 0);for (int j = 1; j < log2(n) + 1; j++) {for (int i = 1; i + (1 << (j - 1)) <= n; i++) {f[i][j] = my_min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);}}int p = lca(s, t);int cnt = 0;for (; s != p; s = f[dfn[s]][0]) {int tt = 1;for (int i = 1; i <= a; i++) {int P = lca(U[i], V[i]);if (lca(P, s) == P && (lca(s, U[i]) == s || lca(s, V[i]) == s)) {tt = 0;break;}}cnt += tt;}for (;; t = f[dfn[t]][0]) {int tt = 1;for (int i = 1; i <= a; i++) {int P = lca(U[i], V[i]);if (lca(P, t) == P && (lca(t, U[i]) == t || lca(t, V[i]) == t)) {tt = 0;break;}}cnt += tt;if (t == p) break;}cout << cnt;}
  • 由于输入数据量达到百万级别,改用 getchar 快速读入可以节约时间
#include <iostream>
#include "bit"
#include "vector"
#include "unordered_set"
#include "unordered_map"
#include "set"
#include "queue"
#include "algorithm"
#include "bitset"
#include "cstring"
#include "cmath"using namespace std;const int N = 1e6 + 1, M = 1e5 + 1;
int n, a, U[M], V[M], s, t, f[N][21], id, dfn[N];
vector<int> e[N];void dfs(int u, int p) {f[dfn[u] = ++id][0] = p;for (int v: e[u]) {if (v != p) {dfs(v, u);}}
}inline int read() {int s = 0, w = 1;int ch = getchar();while (ch < '0' || ch > '9') { if (ch == '-') w = -1; ch = getchar(); }while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar();}return s * w;
}inline int my_min(int x, int y){return dfn[x] < dfn[y] ? x : y;
}int lca(int x, int y) {if (x == y) return x;x = dfn[x], y = dfn[y];if (x > y) swap(x, y);int d = (int)log2(y - x);x++;// 求 x y 之间 dfn 最小的那个数return my_min(f[x][d], f[y - (1 << d) + 1][d]);
}int main() {n = read(), a = read();for (int i = 1; i < n; i++) {int x, y;x = read(), y = read();e[x].push_back(y);e[y].push_back(x);}for (int i = 1; i <= a; i++) U[i] = read(), V[i] = read();//scanf("%d %d", &U[i], &V[i]);s = read(), t = read();dfs(1, 0);for (int j = 1; j < log2(n) + 1; j++) {for (int i = 1; i + (1 << (j - 1)) <= n; i++) {f[i][j] = my_min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);}}int p = lca(s, t);int cnt = 0;for (; s != p; s = f[dfn[s]][0]) {int tt = 1;for (int i = 1; i <= a; i++) {int P = lca(U[i], V[i]);if (lca(P, s) == P && (lca(s, U[i]) == s || lca(s, V[i]) == s)) {tt = 0;break;}}cnt += tt;}for (;; t = f[dfn[t]][0]) {int tt = 1;for (int i = 1; i <= a; i++) {int P = lca(U[i], V[i]);if (lca(P, t) == P && (lca(t, U[i]) == t || lca(t, V[i]) == t)) {tt = 0;break;}}cnt += tt;if (t == p) break;}cout << cnt;
}

结果

用树上倍增求最近公共祖先的时间
在这里插入图片描述
用 dfn 序列求最近公共祖先的时间
在这里插入图片描述
改用快速读入时通过的时间
在这里插入图片描述

小结

这高低复杂度用树上差分好像复杂度更优一点

http://www.dtcms.com/wzjs/487021.html

相关文章:

  • 免费做优化的网站竞价开户推广
  • 三河网站建设-七天网络杭州上城区抖音seo有多好
  • 牛商的网站后台黑龙江暴雪预警
  • 南京建设银行官方网站短视频如何引流与推广
  • 微网官方网站广告推广计划
  • 做网站的职位叫什么seo1搬到哪里去了
  • 选择网站开发公司的标准关键信息基础设施安全保护条例
  • 个人做动漫资源网站旺道网站优化
  • 啤酒网站建设百度推广怎么操作流程
  • 英文外贸网站制作贴吧高级搜索
  • 中国上市公司名单大全长沙专业竞价优化公司
  • 华硕固件做网站6注册百度账号免费
  • 电子商务 做网站网站自动秒收录工具
  • wordpress模板最新郑州网站关键词优化公司哪家好
  • 网站开发兼职团队合肥seo推广培训班
  • 建设 信用中国 网站seo网站关键词优化
  • html企业网站怎么做拼多多标题关键词优化方法
  • 找一些好的网站建设案例优化什么建立生育支持政策体系
  • 可以做视频网站的源码宁波seo外包
  • 做机械网站免费广告
  • 人人车网站建设成都多享网站建设公司
  • 网站建设微信运营公司宁波优化推广找哪家
  • wordpress 配置价格表网站seo关键词优化
  • 微信小程序商城软件开发网站seo公司哪家好
  • 做地方特产的网站百度流量
  • 安溪住房和城乡规划建设局网站网站seo置顶
  • 网站建站网站看看上海疫情突然消失的原因
  • 免费网页设计作业成品大一seo关键词优化工具
  • c 做网站怎么显示歌词淘宝seo是指什么
  • emlog转移到wordpress关键词排名关键词优化