点的距离(模板题)

树中两点间的距离就是d[u] + d[v] - 2 * d[lca(u, v)]

#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std; const int MAXN = 1e5 + 10;
const int MAXM = 20;
struct Edge { int to, next; };
Edge e[MAXN << 1];
int head[MAXN], num, n;
int up[MAXN][MAXM + 10], d[MAXN]; void AddEdge(int from, int to)
{
e[num] = Edge{to, head[from]};
head[from] = num++;
} void dfs(int u, int fa)
{
for(int i = head[u]; ~i; i = e[i].next)
{
int v = e[i].to;
if(v == fa) continue;
d[v] = d[u] + 1;
up[v][0] = u;
dfs(v, u);
}
} void get_up()
{
_for(j, 1, MAXM)
_for(i, 1, n)
up[i][j] = up[up[i][j-1]][j-1];
} int lca(int u, int v)
{
if(d[u] < d[v]) swap(u, v);
for(int i = MAXM; i >= 0; i--)
if(d[up[u][i]] >= d[v])
u = up[u][i];
if(u == v) return u;
for(int i = MAXM; i >= 0; i--)
if(up[u][i] != up[v][i])
u = up[u][i], v = up[v][i];
return up[u][0];
} int main()
{
memset(head, -1, sizeof(head));
num = 0; scanf("%d", &n); REP(i, 1, n)
{
int u, v;
scanf("%d%d", &u, &v);
AddEdge(u, v); AddEdge(v, u);
} dfs(1, -1);
get_up(); int q; scanf("%d", &q);
while(q--)
{
int u, v;
scanf("%d%d", &u, &v);
printf("%d\n", d[u] + d[v] - 2 * d[lca(u, v)]);
} return 0;
}

暗的连锁

这道题首先有个转化

切两刀能不能切断,取决于非树边,因为非树边会构成环

那么可以把非树边构成的环上所有的树边都覆盖一次

如果只覆盖一次,那么显然有唯一解

如果没有被覆盖,那就加上非树边的数目,因为第二刀可以切任意一条非树边

如果覆盖两次以上,那么两刀是不能解决问题的。

所以就有维护每条边被覆盖了多少次

这里用到了树上差分,f[u]表示u与u的父亲连的边的覆盖次数

对于非树边u, v,让f[u]++, f[v]++, f[lca(u, v)]--

最后在“前缀和回来”,即统计所有子树的值加起来,就是答案

最后注意计算答案的时候根的f数组不算,因为根没有父亲

#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std; const int MAXN = 1e5 + 10;
const int MAXM = 20;
struct Edge{ int to, next; };
Edge e[MAXN << 1];
int head[MAXN], num, n, m;
int up[MAXN][MAXM + 10], d[MAXN];
int f[MAXN]; void read(int& x)
{
int f = 1; x = 0; char ch = getchar();
while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); }
while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
x *= f;
} void AddEdge(int to, int from)
{
e[num] = Edge{to, head[from]};
head[from] = num++;
} void dfs(int u, int fa)
{
for(int i = head[u]; ~i; i = e[i].next)
{
int v = e[i].to;
if(v == fa) continue;
d[v] = d[u] + 1;
up[v][0] = u;
dfs(v, u);
}
} int dp(int u, int fa)
{
for(int i = head[u]; ~i; i = e[i].next)
{
int v = e[i].to;
if(v == fa) continue;
dp(v, u);
f[u] += f[v];
}
} void init()
{
dfs(1, -1);
_for(j, 1, MAXM)
_for(i, 1, n)
up[i][j] = up[up[i][j - 1]][j - 1];
} int lca(int u, int v)
{
if(d[u] < d[v]) swap(u, v);
for(int i = MAXM; i >= 0; i--)
if(d[up[u][i]] >= d[v])
u = up[u][i];
if(u == v) return u;
for(int i = MAXM; i >= 0; i--)
if(up[u][i] != up[v][i])
u = up[u][i], v = up[v][i];
return up[u][0];
} int main()
{
read(n);read(m);
memset(head, -1, sizeof(head)); num = 0;
REP(i, 1, n)
{
int u, v; read(u), read(v);
AddEdge(u, v); AddEdge(v, u);
} init();
_for(i, 1, m)
{
int u, v; read(u), read(v);
f[u]++; f[v]++; f[lca(u, v)] -= 2;
} dp(1, -1);
int ans = 0;
_for(i, 2, n)
{
if(f[i] == 1) ans++;
if(f[i] == 0) ans += m;
}
printf("%d\n", ans); return 0;
}

最新文章

  1. 协程--gevent模块(单线程高并发)
  2. sqlalchemy(一)基本操作
  3. preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead
  4. I18N
  5. 使用JMeter创建数据库(Mysql)测试
  6. Android:ScaleType设置图片
  7. While reading XXX pngcrush caught libpng error: N
  8. Spring MVC之Action返回类型
  9. Canvas画布实现自定义时钟效果
  10. 九度OJ 1017 还是畅通工程
  11. 【算法导论】图的深度优先搜索遍历(DFS)
  12. printf(&quot;Hello 2018!&quot;);
  13. Redis知识整理
  14. GBDT 详解分析 转+整理
  15. MONGODB(四)——DBObject与JavaBean转换
  16. H - Gold Coins(2.4.1)
  17. VS2010与Qt5.1.0集成(非源码方式)
  18. webstorm 打包angular Module build failed: Error: No PostCSS Config found
  19. centos6.8 mysql5.6.34 root密码重置
  20. 【转】WKT、SRID、EPSG概念

热门文章

  1. 【hiho一下 第四周】Trie图
  2. jQuery(基本事件)
  3. HDU 3698 Let the light guide us
  4. 线程锁的机制Lock
  5. [Preference] How to avoid Forced Synchronous Layout or FSL to improve site preference
  6. Light OJ 1288 Subsets Forming Perfect Squares 高斯消元求矩阵的秩
  7. 本地 配置 Memcache
  8. zzulioj--1858--单词翻转(模拟)
  9. 编译最新版webrtc源码和编译好的整个项目10多个G【分享】
  10. Navicat 连接 Mysql 报2059错误的原因以及解决方法