3124: [Sdoi2013]直径

Posted mjtcn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3124: [Sdoi2013]直径相关的知识,希望对你有一定的参考价值。

3124: [Sdoi2013]直径

https://www.lydsy.com/JudgeOnline/problem.php?id=3124

 

分析:

  所有直径都经过的边,一定都是连续的一段。(画个图,反证一下)

  然后可以求出一条直径后,可以对每个点求出不经过直径到达的最远的距离。

  然后判断一下,找到左边分叉的最后一个,右边分叉的第一个,中间的点就是所有直径都经过的点。

 

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 
 5 inline int read() {
 6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==-)f=-1;
 7     for (;isdigit(ch);ch=getchar())x=x*10+ch-0;return x*f;
 8 }
 9 
10 const int N = 200100;
11 
12 int head[N], q[N], fa[N], nxt[N<<1], to[N<<1], Enum;
13 LL dis[N], dist[N], val[N<<1], Len = 0, Mx = 0;
14 int Root, Qd, Zd, tot;
15 bool vis[N];
16 
17 inline void add_edge(int u,int v,int w) {
18     ++Enum; to[Enum] = v; val[Enum] = w; nxt[Enum] = head[u]; head[u] = Enum;
19     ++Enum; to[Enum] = u; val[Enum] = w; nxt[Enum] = head[v]; head[v] = Enum;
20 }
21 
22 void dfs1(int u,int pa) {
23     fa[u] = pa;
24     if (dis[u] > Len) {
25         Len = dis[u]; Root = u;
26     }
27     for (int i=head[u]; i; i=nxt[i]) {
28         int v = to[i];
29         if (v == pa) continue;
30         dis[v] = dis[u] + val[i];
31         dfs1(v, u);
32     }
33 }
34 
35 void dfs2(int u,int pa) {
36     vis[u] = true;
37     if (dist[u] > Mx) {
38         Mx = dist[u]; Root = u;
39     }
40     for (int i=head[u]; i; i=nxt[i]) {
41         int v = to[i];
42         if (v == pa || vis[v]) continue;
43         dist[v] = dist[u] + val[i];
44         dfs2(v, u);
45     }
46 }
47 
48 int main() {
49     
50     int n = read();
51     for (int i=1; i<n; ++i) {
52         int u = read(), v = read(), w = read();
53         add_edge(u, v, w);
54     }
55     dfs1(1, 0);
56     Len = 0; Qd = Root; dis[Qd] = 0;
57     dfs1(Root, 0);
58     Zd = Root;
59     
60     for (int i=Zd; i; i=fa[i]) q[++tot] = i, vis[i] = true;
61     
62     int L = tot, R = 1;
63     for (int i=tot; i>=1; --i) {
64         Mx = 0;dfs2(q[i], 0);
65         if (!Mx) continue;
66         if (Mx == dis[q[i]]) L = i; // 保证所有直径都经过,左边分叉的最后一个 
67         if (Len - dis[q[i]] == Mx) {R = i; break;} // 右边分叉的第一个
68     }
69     cout << Len << "
" << L - R;    
70     return 0;
71 }

 

以上是关于3124: [Sdoi2013]直径的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3124: [Sdoi2013]直径

SDOI2013 R1 Day1

SDOI2013 直径(树的直径必经边)

[SDOI2013]直径(树的直径)

[树的直径] SDOI2013 直径

[Sdoi2013]直径(树的直径)