标签:maxdis Paths int maxv Two dfs CodeForces edges tag
题目大意:
给定一棵权值为\(1\)的树,从中两条最长的路径且两者没有公共节点,求最大的二路径乘积。
思路:
观察到\(n\)的范围很小,可以枚举每条要删的边,再在两个子树中求树的直径,相乘即为答案。
本题我采用两次\(bfs\)的方式求树的直径。
另外,记得打上删除标记。
时间复杂度\(O(n^2)\)。
Code:
#include <bits/stdc++.h>
using namespace std;
const int N = 224;
//maxv:源点能到的最远点,maxdis:最远点对应的距离,
struct Edge {
int from, to, next, w;
bool tag;
}edges[N << 1];
int head[N], maxdis,maxv, ne;
void init(){ memset(head, -1, sizeof(head)); maxv = maxdis = ne = 0; }
void add(int u, int v, int w) {
edges[ne] = { u, v, head[u], w, true };
head[u] = ne++;
}
//u:dfs的源点,f: u点的父节点,d2s:u点到源点的距离
void dfs(int u, int f, int d2s) {
if (maxdis < d2s){
maxdis = d2s;
maxv = u;
}
for (int e = head[u]; e != -1; e = edges[e].next) {
int v = edges[e].to, w = edges[e].w;
if (!edges[e].tag) continue;
if (v == f) continue; //父节点已经访问过,防止重复遍历,相反孩子不会重复遍历。
dfs(v, u, d2s + w);
}
}
int main() {
int ans = 0;
int n; cin >> n;
memset(head, -1, sizeof(head));
for (int i = 1; i < n; i++) {
int u, v, w = 1; cin >> u >> v;
add(u, v, w), add(v, u, w);
}
for (int i = 0; i < ne; i += 2) {
edges[i].tag = edges[i^1].tag = 0; //双向边都堵住
int u = edges[i].from, v = edges[i].to;
dfs(u, -1, 0); //从结点u开始遍历,找到最远点maxv及对应的最远距离maxdis
maxdis = 0;
dfs(maxv, -1, 0);//从结点maxv开始遍历,找到最远点对应的距离maxdis
int mul1 = maxdis; maxv = maxdis = 0;
dfs(v, -1, 0);
maxdis = 0;
dfs(maxv, -1, 0);
int mul2 = maxdis; maxv = maxdis = 0;
ans = max(ans, mul1 * mul2);
edges[i].tag = edges[i^1].tag = 1;
}
cout << ans << endl;
return 0;
}
标签:maxdis,Paths,int,maxv,Two,dfs,CodeForces,edges,tag 来源: https://www.cnblogs.com/Nepenthe8/p/13798517.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。