D. Minimum Diameter Tree(思维)树的直径

给定n个点和n-1条边的无向树,目标是构造直径最小的树,其中某些边的权值可能为0。树的直径是任意两点间路径的最大权值。解决方案是将度数为1的边赋值,使得总权值均等分配,从而最小化直径。

树的直径

题目链接: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; 
}

在这里插入图片描述

2.1 图模型定义 (类型:无向、加权/无权、是否含多重边等;顶点与边的实际含义(如:顶点=城市,边=公路)) 2.2 构建方法 (数据来源:真实数据(需注明出处)或仿真生成(如随机图模型);工具:Python的NetworkX) 2.3 可视化展示 3、图的性质分析与计算 输出点、边数量------- num_nodes = G.number_of_nodes() num_edges = G.number_of_edges() 输出一条边的属性 举例 判断是否有点 G.has_node(a) 判断是否有边 G.has_edge(u,v) 输出点a的所有邻居 G.neighbors(a) 输出图邻接对象 G.adj 输出度序列:非增序列 G.degree() 最大度: 最小度: 删除图上度最大的点 输出邻接矩阵 A adj_matrix = nx.adjacency_matrix(G) adj_dense = adj_matrix.todense() 输出关联矩阵 M inc_matrix = nx.incidence_matrix(G) inc_dense = inc_matrix.todense() 输出生成子图 edges_to_keep = [(1, 2), (2, 3), (3, 4), (4, 1)] H = nx.edge_subgraph(G, edges_to_keep) 输出最小生成 mst = nx.minimum_spanning_tree(G) 输出点导出子图 H = G.subgraph(nodes_subset) 输出边导出子图 edges_subset = [(1, 2), (3, 4)] H = nx.edge_subgraph(G, edges_subset) 计算图的连通分支数目num_components = nx.number_connected_components(G) components = list(nx.connected_components(G)) print("各连通分支的节点集合:", components) 找出图的割点和割边 cut_vertices = list(nx.articulation_points(G)) cut_edges = list(nx.bridges(G)) 找出图的补图 G_complement = nx.complement(G) 计算所有节点对的最短路径长度 lengths = dict(nx.all_pairs_shortest_path_length(G)) 计算半径 r = nx.radius(G) 计算直径 d = nx.diameter(G) 获取中心点 center_nodes = nx.center(G) 计算周长 cycles = list(nx.simple_cycles(G.to_directed())) longest_cycle = max(cycles, key=len, default=[]) circumference = len(longest_cycle) 点连通度 # 图的整体点连通度 k_v = nx.node_connectivity(G) # 两点间的点连通度(如节点 0 和 33) k_v_pair = nx.node_connectivity(G, s=0, t=33) 边连通度 # 图的整体边连通度 k_e = nx.edge_connectivity(G) # 两点间的边连通度 k_e_pair = nx.edge_connectivity(G, s=0, t=33) 找出最小点割集 cut_set = nx.minimum_node_cut(G) 找出最小边割集 cut_edges = nx.minimum_edge_cut(G) 计算最大匹配 matching = nx.algorithms.matching.max_weight_matching(G, maxcardinality=True) # 输出结果(每条匹配边) print("最大匹配结果:") for u, v in matching: print(f"{u} -- {v}") 按照上面格式,根据代码写图模型定义,构建方法,可视化展示,图的性质分析与计算
05-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值