题目链接:https://codeforces.com/contest/1087/problem/D
题意:给你n个点,n-1条边,构成一颗无向树,树的总权值为s,现在让你构造一颗直径最小的树,一颗树的直径是最大的两点路径权值之和。最后输出直径。
题解:因为某些边的权值可以为0,那么我们只要将度数为1的边赋值,其它不赋值,这样的话,这棵树的直径就是两条度数为1的边的权值和(因为这两之间的路的权值都为0了),那么我们要尽可能的使树的直径小,那就只能把树的总权值均等分了。
vector写法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e6 + 7;
//char str[maxn][maxn];
int a[maxn],b[maxn],c[maxn];
priority_queue <int,vector<int>,greater<int> > q;
std::vector<int> G[maxn];
int main(){
int n , m ;
cin >> n >> m;
for(int i = 1; i < n ; i++){
int u , v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
int ans = 0;
for(auto ve : G){
if(ve.size() == 1) ans ++;
}
printf("%0.8lf\n", (1.0) * m /ans * 2.0);
return 0;
}
前向星写法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e6 + 7;
//char str[maxn][maxn];
int a[maxn],b[maxn],c[maxn];
priority_queue <int,vector<int>,greater<int> > q;
//std::vector<int> G[maxn];
struct edge
{
int to,nxt;
}e[maxn << 1];
int tot ;
int head[maxn];
void add_edge(int u , int v){
e[tot].to = v;
e[tot].nxt = head[u];
head[u] = tot ++;
}
void init(int u , int v){
add_edge(u,v);
add_edge(v,u);
}
int main(){
int n , m ;
memset(head,-1,sizeof head);
cin >> n >> m;
for(int i = 1; i < n ; i++){
int u , v;
cin >> u >> v;
//G[u].push_back(v);
//G[v].push_back(u);
init(u,v);
}
int ans = 0;
for(int i = 1; i <= n ; i++){
int sum = 0;
for(int j = head[i]; ~j; j = e[j].nxt){
// cout << e[j].to << endl;
sum ++;
//dfs()
}
if(sum == 1) ans ++;
}
printf("%0.8lf\n", (1.0) * m /ans * 2.0);
//cout << (1.0) * m /ans * 2.0 << endl;
return 0;
}