标签:
一句话题意:在一棵n个结点的树上,有m对点对,若将其中一条边的边权修改成0,求m对点对的最大距离的最小值。
这道题正解是二分+树上差分,可是我一开始并没有想到,而是想了另外一个方法。
预处理每对节点的距离(LCA),同时找出最长链,缩短的边一定在这条链上。此过程为O(nlogn)。
枚举链上每一条边,对于所有点对,可以分成两种了:1)经过这条边的点对;2)不经过的。
判断方法:割掉这条边,判断两点是否连通,仍连通,说明不经过,反之经过。于是一棵树就被拆成了两棵。对于经过的路径(包含最长的),距离都会被缩短,但因为最长的路径存在,所以无需考虑经过的其他路径;而不经过的路径之中取个最大值,将最长路径减去边的权和不经过该边的最大值中再取最大值,枚举所有边的时候再取个最小值就OK了。
在链上一条接着一条判断边时,其中的一棵子树会获得更多的节点,其中可能就包括端点,获得其中一个表示此点对经过该边,获得另一个表示不经过了,因为都在子树中连通。这个过程中判断完所有的边后,所有节点都转至子树中,复杂度为O(n)。
对于判断不经过该边的点对的最大值,维护个线段树,开始时维护第i个点对距离d[i],在得到一个端点后修改成0,另一个也得到时修改回来。此过程为O(nlogn)。
分析结束。
一开始写错了几个细节,15pts;
后来改成了80pts;
再后来改成了95pts;
被一个答案为0的数据卡到了,改正后,100pts。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 6 using namespace std; 7 8 #define re register int 9 #define LL long long 10 #define rep(i, x, y) for (register int i = x; i <= y; ++i) 11 #define repd(i, x, y) for (register int i = x; i >= y; --i) 12 #define maxx(a, b) a = max(a, b) 13 #define minn(a, b) a = min(a, b) 14 15 inline int read() { 16 int w = 0, f = 1; char c = getchar(); 17 while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar(); 18 while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ 48), c = getchar(); 19 return w * f; 20 } 21 22 const int maxn = 3e5 + 5; 23 24 struct Edge { 25 int u, v, w, pre; 26 }; 27 28 struct Gph { 29 int n, m, G[maxn]; 30 Edge edges[maxn << 1]; 31 void init(int n) { 32 this->n = n; 33 m = 0; 34 memset(G, 0, sizeof(G)); 35 } 36 void AddEdge(int u, int v, int w) { 37 edges[++m] = (Edge){u, v, w, G[u]}; 38 G[u] = m; 39 } 40 } ES1, ES2; 41 42 struct LCA { 43 int fa[20][maxn], dis[20][maxn], n, m, dep[maxn]; 44 void dfs(int u, int f) { 45 rep(i, 1, log2(dep[u])) fa[i][u] = fa[i-1][fa[i-1][u]], dis[i][u] = dis[i-1][u] + dis[i-1][fa[i-1][u]]; 46 for (re i = ES1.G[u]; i; i = ES1.edges[i].pre) { 47 Edge &e = ES1.edges[i]; 48 if (e.v == f) continue; 49 fa[0][e.v] = u, dep[e.v] = dep[u] + 1, dis[0][e.v] = e.w; 50 dfs(e.v, u); 51 } 52 } 53 int query(int u, int v) { 54 if (dep[u] < dep[v]) u ^= v ^= u ^= v; 55 re res = 0; 56 if (dep[u] != dep[v]) { 57 re dt = dep[u] - dep[v], t = 0; 58 while (dt) { 59 if (dt & 1) res += dis[t][u], u = fa[t][u]; 60 t++; 61 dt >>= 1; 62 } 63 } 64 if (u == v) return res; 65 repd(i, log2(dep[u]), 0) 66 if (fa[i][u] != fa[i][v]) res += dis[i][u] + dis[i][v], u = fa[i][u], v = fa[i][v]; 67 return res + dis[0][u] + dis[0][v]; 68 } 69 } LCA; 70 71 struct SegTree { 72 int val[maxn << 4]; 73 #define lson (o << 1) 74 #define rson (o << 1 | 1) 75 void pushup(int o) { 76 val[o] = max(val[lson], val[rson]); 77 } 78 void build(int o, int l, int r, int *a) { 79 if (l == r) { val[o] = a[l]; return; } 80 re mid = l + r >> 1; 81 build(lson, l, mid, a); 82 build(rson, mid+1, r, a); 83 pushup(o); 84 } 85 void update(int o, int l, int r, int x, int v) { 86 if (l == r) { val[o] = v; return; } 87 re mid = l + r >> 1; 88 if (x <= mid) update(lson, l, mid, x, v); 89 else update(rson, mid+1, r, x, v); 90 pushup(o); 91 } 92 int query() { 93 return val[1]; 94 } 95 } ST; 96 97 int n, m, l[maxn], r[maxn], dis[maxn], vis[maxn], max_i, fa[maxn], d[maxn], ans; 98 99 void dfs1(int u) { 100 vis[u] = 1; 101 for (re i = ES1.G[u]; i; i = ES1.edges[i].pre) { 102 Edge &e = ES1.edges[i]; 103 if (vis[e.v]) continue; 104 fa[e.v] = u; d[e.v] = e.w; 105 dfs1(e.v); 106 } 107 } 108 109 int starr[maxn << 1], g[maxn], cnt = 0, val[maxn << 1], time0[maxn]; 110 111 void AddPoint(int x, int i) { 112 starr[++cnt] = g[x]; 113 val[cnt] = i; 114 g[x] = cnt; 115 } 116 117 void dfs2(int u) { 118 vis[u] = 0; 119 for (re i = g[u]; i; i = starr[i]) { 120 time0[val[i]]++; 121 if (time0[val[i]] == 1) ST.update(1, 1, n, val[i], 0); 122 else ST.update(1, 1, n, val[i], dis[val[i]]); 123 } 124 for (re i = ES1.G[u]; i; i = ES1.edges[i].pre) { 125 Edge &e = ES1.edges[i]; 126 if (!vis[e.v] || e.v == fa[u]) continue; 127 dfs2(e.v); 128 } 129 } 130 131 int main() { 132 n = read(), m = read(); 133 ES1.init(n); 134 rep(i, 1, n-1) { 135 re u = read(), v = read(), w = read(); 136 ES1.AddEdge(u, v, w); 137 ES1.AddEdge(v, u, w); 138 } 139 LCA.fa[0][1] = 1; 140 LCA.dfs(1, -1); 141 rep(i, 1, m) { 142 l[i] = read(); r[i] = read(); 143 AddPoint(l[i], i); 144 AddPoint(r[i], i); 145 dis[i] = LCA.query(l[i], r[i]); 146 if (dis[i] > dis[max_i]) max_i = i; 147 } 148 ST.build(1, 1, n, dis); 149 dfs1(l[max_i]); 150 ans = dis[max_i]; 151 while (r[max_i] != l[max_i]) { 152 dfs2(r[max_i]); 153 minn(ans, max(ST.query(), dis[max_i] - d[r[max_i]])); 154 r[max_i] = fa[r[max_i]]; 155 } 156 printf("%d", ans); 157 return 0; 158 }
标签: 来源: https://www.cnblogs.com/ac-evil/p/9780450.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。