Codeforces Round #615 (Div. 3) F. Three Paths on a Tree

F. Three Paths on a Tree

原题链接:https://codeforces.com/contest/1294/problem/F

题目大意:

给定一棵树,选出三点,使三点连成的j简单路径最大。简而言之,三个点连成的边的集合大小。

解题思路:

假设任取一点为三点连线的公共点,最长路径就是这个点到其他三个点的三条最长边之和,可知这个点一定在直径上(画图分析假设不在时的最长路径可反证)。所以先求出树的直径,在使用$ans =(a b+a c+b c) / 2$遍历可以得到第三个点。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2e5+10;
 4 vector<int> a[maxn];
 5 int n,vis[maxn],dis1[maxn],dis2[maxn],dis[maxn],pos;
 6 void bfs(int x){
 7     memset(vis,0,sizeof(vis));
 8     memset(dis,0,sizeof(dis));
 9     pos=x;
10     vis[x]=1,dis[x]=0;
11     queue<int> q;
12     q.push(x);
13     while(!q.empty()){
14         int u=q.front();q.pop();
15         for(int i=0;i<a[u].size();i++){
16             if(!vis[a[u][i]]){
17                 vis[a[u][i]]=1;
18                 dis[a[u][i]]=dis[u]+1;
19                 q.push(a[u][i]);
20                 if(dis[a[u][i]]>dis[pos]) pos=a[u][i];
21             }
22         }
23     }
24 }
25 int main(){
26     scanf("%d",&n);
27     int u,v;
28     for(int i=1;i<n;i++){
29         scanf("%d%d",&u,&v);
30         a[u].push_back(v);
31         a[v].push_back(u);
32     }
33        int a,b,c;
34        bfs(1);
35     a=pos;
36     bfs(pos);
37     b=pos;
38        for(int i=1;i<=n;i++){
39         dis1[i]=dis[i];
40     }
41        bfs(pos);
42        for(int i=1;i<=n;i++){
43        dis2[i]=dis[i];
44     }
45        c=0;
46        for(int i=1;i<=n;i++){
47         if(dis1[i]+dis2[i]>dis1[c]+dis2[c]&&i!=a&&i!=b){
48             c=i;
49         }
50     }
51        int ans=(dis1[b]+dis1[c]+dis2[c])/2;
52        cout<<ans<<endl<<a<<" "<<b<<" "<<c;
53     return 0;
54 }

原文地址:https://www.cnblogs.com/meanttobe/p/12255599.html

时间: 2024-10-11 07:41:18

Codeforces Round #615 (Div. 3) F. Three Paths on a Tree的相关文章

Codeforces Round #486 (Div. 3) F. Rain and Umbrellas

Codeforces Round #486 (Div. 3) F. Rain and Umbrellas 题目连接: http://codeforces.com/group/T0ITBvoeEx/contest/988/problem/E Description Polycarp lives on a coordinate line at the point x=0. He goes to his friend that lives at the point x=a. Polycarp can

Codeforces Round #501 (Div. 3) F. Bracket Substring

题目链接 Codeforces Round #501 (Div. 3) F. Bracket Substring 题解 官方题解 http://codeforces.com/blog/entry/60949 ....看不懂 设dp[i][j][l]表示前i位,左括号-右括号=j,匹配到l了 状态转移,枚举下一个要填的括号,用next数组求状态的l,分别转移 代码 #include<bits/stdc++.h> using namespace std; const int maxn = 207;

Codeforces Round #615 (Div. 3) A-F简要题解

contest链接:https://codeforces.com/contest/1294 A. 给出a.b.c三个数,从n中分配给a.b.c,问能否使得a = b = c.计算a,b,c三个数的差值之和,n对其取余,判断是否为0即可. AC代码: 1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring>

Codeforces Round #392 (Div. 2) F. Geometrical Progression

原题地址:http://codeforces.com/contest/758/problem/F F. Geometrical Progression time limit per test 4 seconds memory limit per test 256 megabytes input standard input output standard output For given n, l and r find the number of distinct geometrical pro

Codeforces Round #531 (Div. 3) F. Elongated Matrix(状压DP)

F. Elongated Matrix 题目链接:https://codeforces.com/contest/1102/problem/F 题意: 给出一个n*m的矩阵,现在可以随意交换任意的两行,最后从上到下,从左到右形成一个序列s1,s2.....snm,满足对于任意相邻的两个数,它们差的绝对值的最大值为k. 现在问怎么交换行与行,可以使得最后的这个k最大. 题解: 人生中第一道状压dp~其实还是参考了这篇博客:https://blog.csdn.net/CSDNjiangshan/art

Codeforces Round #548 (Div. 2) F splay(新坑) + 思维

https://codeforces.com/contest/1139/problem/F 题意 有m个人,n道菜,每道菜有\(p_i\),\(s_i\),\(b_i\),每个人有\(inc_j\),\(pref_j\),一个人可以买一道菜的条件是 1. \(p_i \leq inc_j \leq s_i\) 2. \(|b_i - pref_j| \leq inc_j-p_i\) ,问每个人分别能买多少道菜 题解 转化一下公式 \(p_i \leq inc_j \leq s_i\) 下面两个满

Codeforces Round #549 (Div. 2) F 数形结合 + 凸包(新坑)

https://codeforces.com/contest/1143/problem/F 题意 有n条形如\(y=x^2+bx+c\)的抛物线,问有多少条抛物线上方没有其他抛物线的交点 题解 \(y=x^2+bx+c=>y+x^2=bx+c\),转换为点\((x,y+x^2)\)在bx+c的直线上 两个点确定一条抛物线,同时也确定了一条直线 需要选择最上面那些点相邻确定的抛物线,所以维护一个上凸包即可 维护上凸包,当前点在前进方向左边需要向后退,cross(a,b)>=0 代码 #inclu

Codeforces Round #530 (Div. 2)F Cookies (树形dp+线段树)

题:https://codeforces.com/contest/1099/problem/F 题意:给定一个树,每个节点有俩个信息x和t,分别表示这个节点上的饼干个数和先手吃掉这个节点上一个饼干的的时间.然后有先手和后手俩个人. ?先手可以这么操作:在规定总时间T到达某个节点然后一定要返回根节点1,期间可以选择吃掉某些节点上的某些饼干(前提是保证剩下的时间能够回到根节点): ?后手可以这么操作:在先手到达的位置和这个位置的孩子之间的连边选择一条让先手吃得更多的边摧毁掉,也可以跳过这个过程: 问

Codeforces Round #629 (Div. 3) F - Make k Equal (离散化 树状数组维护前缀和)

https://codeforces.com/contest/1328/problem/F 首先把a数组处理成pair对(num,cnt),表示数字num有cnt个,然后按num升序排序离散化一下. 对于一个数x,若想使得小于x的数字都变成x,必须先把所有小于x的数变成x-1,然后再+1变成x. 同理,要使得大于x的数变成x,必须把所有大于x的数字变成x+1,然后再-1变成x. 以上是题意所要求的必须操作. 思路: 1. 用f[i]数组记录离散化后前i大的数字的总数,那么对于任意第i大数字,可以