2022.9.26 闲话 / Dijkstra No (B: htaaywaai)

因为一些原因所以早点发闲话,晚了就没机会发了 .

标题是一个解密

关于树的直径的一个结论(Anton and Tree)

题目描述

题目链接 .

给一棵 \(n\) 个节点的树,每个点为黑色或白色,一次操作可以使一个相同颜色的连通块变成另一种颜色,求使整棵树变成一种颜色的最少操作数 .

\(n\le 2\times 10^5\) .

解答(含详细证明)

首先把每个同色连通块缩成一个点,并查集实现是 \(O(n\alpha(n))\) 的,Tarjan 实现就是 \(O(n)\) 的 .

这样问题就可以变成:

Flood Fill

给一棵树 \(\mathcal T\),对于一个点 \(u\),其代价定义为 \(u\)\(\mathcal T\) 上所有点距离之最大值 .

对于每个点 \(u\),问最小代价是多少 .

结论是满足条件的 \(u\) 就是直径的中点(如果直径长度是偶数那么有两个中点).

反证法,如果有一个 \(u'\) 是最优解:

  • 如果 \(u'\) 不在树的直径上,于是贡献在直径端点上(这可以根据直径的定义得到),那么考察直径上随便一个点 \(u\) 可以发现 \(u'\) 一定不优于 \(u\) .

  • 如果 \(u'\) 在直径上但不在中点上,假设 \(u'\) 的出点中离直径中点 \(m\) 最近的点是 \(u\),那么考虑以 \(u'\) 为根,\(u\) 的子树产生的贡献(不算直径上的点),这一定是比原来小的 .

    可以通过反证法得知子树外产生的贡献一定是不如子树内的,于是 \(u'\) 不如 \(u\)(逐步调整就可以得到 \(m\) 才是最优的,但是这里是反证法所以没必要去说明这个).

把上面的证明的脚手架展示出来就比较显然明了了,因为我 so lazy 所以懒得画图了,可能有点晦涩 .

但是直径可能有很多啊,我们还需要证明所有直径的中点重合,不然上面的证明就是有点问题的 .

若树上所有边边权均为正,则树的所有直径中点重合 .

还是用反证法 . 令两条中点不重合的直径端点分别为 \((u_1,v_1)\)\((u_2,v_2)\),中点设为 \(m_1,m_2\) .

\(\operatorname{dist}(u_1,m_1)=\operatorname{dist}(m_1,v_1)=\operatorname{dist}(u_2,m_2)=\operatorname{dist}(m_2,v_2)\) .

那么 \(\operatorname{dist}(u_1,v_2)=\operatorname{dist}(u_1,m_1)+\operatorname{dist}(m_1,m_2)+\operatorname{dist}(m_2,v_1)>\operatorname{dist}(u_1,m_1)+\operatorname{dist}(m_1,v_1)=\operatorname{dist}(u_1,v_1)\) .

也就是说 \((u_1,v_2)\) 这条路径比 \((u_1,v_1)\) 更长,这与它是直径矛盾,所以直径中点必然重合 .

注:最后一步用的是三角形不等式,这也就限制了树上所有边边权均为正 .

完整代码

因为我不会两次 DFS 求树的直径所以用的树形 DP .

不要像我一样并查集不加路径压缩卡在 TLE #11 无法自拔 .

#include <bits/stdc++.h> 
#define filein(x) {freopen(x".in", "r", stdin);}
#define file(x) {freopen(x".in", "r", stdin); freopen(x".out", "w", stdout);}
#define files(x) {freopen(x".in", "r", stdin); freopen(x".out", "w", stdout);}
template<typename T>
inline T chkmin(T& x, const T& y){if (x > y) x = y; return x;}
template<typename T>
inline T chkmax(T& x, const T& y){if (x < y) x = y; return x;}
template<typename T>
inline bool inrange(T x, T l, T r){return (l <= x) && (x <= r);}
template<typename T>
inline bool inrange(T l, T r, T L, T R){return (L <= l) && (r <= R);}
#define mem(x, a) memset(x, a, sizeof x);
#define cls(x) rep(x, 0)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
inline db sqr(const db& x){return x * x;}
template <typename T>
using pr = pair<T, T>;
typedef pr<int> pii;
typedef pr<ll> pll;
typedef pr<db> pdd;
typedef complex<double> cp;
typedef vector<int> vi;
const int N = 2e5 + 123;
struct dsu
{
	int fa[N];
	inline void reset(){iota(fa, fa+N, 0);}
	dsu(){reset();}
	int get(int x){return fa[x] = (x == fa[x]) ? x : get(fa[x]);}
	inline void merge(int u, int v){fa[get(u)] = get(v);}
}B, W;
template<typename T>
class pool
{
	unordered_map<T, unsigned> pol;
	unsigned cc;
public:
	pool(){cc = 0;}
	~pool() = default;
	unsigned get(T x)
	{
		auto ptr = pol.find(x);
		if (ptr == pol.end()){pol[x] = ++cc; return cc;}
		else return ptr -> second;
	}
	unsigned size()const{return cc;} 
	void clear(){cc = 0; pol.clear();}
};
pool<int> M;
int n, col[N];
vector<int> g[N]; 
inline void addedge(int u, int v){g[u].emplace_back(v);} 
inline void ade(int u, int v){addedge(u, v); addedge(v, u);}
int dp[N], secdp[N];
void dfs(int u, int fa)
{
	for (int v : g[u])
	{
		if (v == fa) continue;
		dfs(v, u);
		if (dp[v] + 1 > dp[u]){secdp[u] = dp[u]; dp[u] = dp[v] + 1;}
		else if (dp[v] + 1 > secdp[u]) secdp[u] = dp[v] + 1;
	}
}
int main()
{
	scanf("%d", &n);
	for (int i=1; i<=n; i++) scanf("%d", col+i);
	vector<pii> ed;
	for (int i=1, u, v; i<n; i++) 
	{
		scanf("%d%d", &u, &v);
		if (col[u] == col[v])
		{
			if (col[u]) B.merge(u, v);
			else W.merge(u, v);
		}
		else ed.emplace_back(make_pair(u, v));
	}
	for (pii e : ed){int u = e.first, v = e.second; ade(M.get(col[u] ? B.get(u) : W.get(u)), M.get(col[v] ? B.get(v) : W.get(v)));}
	dfs(1, 1);
	int ans = 0; n = M.size();
	for (int i=1; i<=n; i++) chkmax(ans, dp[i] + secdp[i]);
	printf("%d\n", (ans + 1) >> 1);
	return 0;
}

杂谈


呃呃,这一波反串黑太秀了 /cy


发现 junk 有中国式帆船的意思,?????

附录

承接上次的百合图

posted @ 2022-09-26 17:57  yspm  阅读(142)  评论(6编辑  收藏  举报
😅​