[CF592D]Super M

Posted skylee的OI博客

tags:

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

题目大意:
给定一颗n个节点树,边权为1,树上有m个点被标记,问从树上一个点出发,经过所有被标记的点的最短路程,以及可行的最小的端点编号。(起终点自选)
M<=N<=123456

思路:
随便定一个标记节点为根,然后以该节点开始遍历,将不是标记节点的叶节点剪掉,剩下的边数为P。求出树的直径L。答案即为2*P-L。
另外注意一定要保证节点编号最小。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<vector>
 4 #include<algorithm>
 5 inline int getint() {
 6     int ch;
 7     while(!isdigit(ch=getchar()));
 8     int x=ch^0;
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^0);
10     return x;
11 }
12 const int N=123457,inf=0x7fffffff;
13 int n,m;
14 bool a[N]={0};
15 struct Edge {
16     int to;
17     bool cut;
18 };
19 std::vector<Edge> e[N];
20 inline void add_edge(const int u,const int v) {
21     e[u].push_back((Edge){v,false});
22     e[v].push_back((Edge){u,false});
23 }
24 int u=inf,x=inf,v=inf,l=0;
25 void find_u(const int x,const int parent,const int depth) {
26     if(depth>l) {
27         l=depth;
28         u=x;
29     }
30     else if(depth==l) {
31         u=std::min(u,x);
32     }
33     for(unsigned int i=0;i<e[x].size();i++) {
34         if(e[x][i].to==parent||e[x][i].cut) continue;
35         find_u(e[x][i].to,x,depth+1);
36     }
37 }
38 void find_v(const int x,const int parent,const int depth) {
39     if(depth>l) {
40         l=depth;
41         v=x;
42     }
43     else if(depth==l) {
44         v=std::min(v,x);
45     }
46     for(unsigned int i=0;i<e[x].size();i++) {
47         if(e[x][i].to==parent||e[x][i].cut) continue;
48         find_v(e[x][i].to,x,depth+1);
49     }
50 }
51 bool cut(const int x,const int parent) {
52     bool ret=true;
53     for(unsigned int i=0;i<e[x].size();i++) {
54         if(e[x][i].to==parent) continue;
55         if(cut(e[x][i].to,x)) {
56             e[x][i].cut=true;
57             n--;
58         }
59         else {
60             ret=false;
61         }
62     }
63     return ret&&!a[x];
64 }
65 int main() {
66     n=getint()-1,m=getint();
67     for(int i=0;i<n;i++) add_edge(getint(),getint());
68     int x=inf;
69     for(int i=0;i<m;i++) {
70         int t=getint();
71         a[t]=true;
72         x=std::min(x,t);
73     }
74     cut(x,0);
75     find_u(x,0,0);
76     find_v(u,0,0);
77     printf("%d\n%d\n",std::min(u,v),(n<<1)-l);
78     return 0;
79 }

 

以上是关于[CF592D]Super M的主要内容,如果未能解决你的问题,请参考以下文章

CF 592D(Super M-虚树直径)

CodeForces - 592D Super M 题解

Codeforces 592D Super M树的直径

树的直径-CF592D Super M

片段中的 super.onCreateView

不立即分离片段