UVA 11354 - Bond (最小生成树 + 树链剖分)

本文详细介绍了如何利用Kruskal算法处理最小生成树问题,并结合树链剖分与线段树进行优化。通过实例分析,展示了算法的实现过程与效率提升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接~~>

做题感悟:这题开始看到时感觉不是树不好处理,一想可以用 Kruskal 处理成树 ,然后就好解决了。

解题思路:

                先用 Kruskal 处理出最小生成树,然后用树链剖分 + 线段树处理就可以了。

代码:

#include<iostream>
#include<sstream>
#include<map>
#include<cmath>
#include<fstream>
#include<queue>
#include<vector>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<bitset>
#include<ctime>
#include<string>
#include<cctype>
#include<iomanip>
#include<algorithm>
using namespace std  ;
#define INT long long int
#define L(x)  (x * 2)
#define R(x)  (x * 2 + 1)
const int INF = 0x3f3f3f3f ;
const double esp = 0.0000000001 ;
const double PI = acos(-1.0) ;
const int mod = 1000000007 ;
const int MY = (1<<5) + 5 ;
const int MX = 100000 + 5 ;
int n ,m ,nx ,idx ,num ;
int head[MX] ,ti[MX] ,siz[MX] ,son[MX] ,father[MX] ,top[MX] ,dep[MX] ;
struct NODE
{
    int u ,v ,w ;
}e[MX] ;
struct MNODE
{
    int u ,v ,w ;
}t[MX] ;
struct Edge
{
    int u ,v ,w ,next ;
}E[MX*2] ;
void addedge(int u ,int v ,int w)
{
    E[num].v = v ; E[num].w = w ; E[num].next = head[u] ; head[u] = num++ ;
    E[num].v = u ; E[num].w = w ; E[num].next = head[v] ; head[v] = num++ ;
}
bool cmp(NODE a ,NODE b)
{
    return a.w < b.w ;
}
int find(int u)
{
    if(father[u] != u)
       return find(father[u]) ;
    else   return u ;
}
void Kruskal()
{
    nx = 1 ;
    int u ,v ,fa ,fb ;
    sort(e ,e+m ,cmp) ;
    for(int i = 0 ;i <= n ; ++i)
        father[i] = i ;
    for(int i = 0 ;i < m ; ++i)
    {
        u = e[i].u ; v = e[i].v ;
        fa = find(u) ;
        fb = find(v) ;
        if(fa != fb)
        {
            father[fa] = fb ;
            addedge(u ,v ,e[i].w) ;
            t[nx].u = u ; t[nx].v = v ; t[nx++].w = e[i].w ;
        }
    }
}
void dfs_find(int u ,int fa)
{
    dep[u] = dep[fa] + 1 ;
    father[u] = fa ;
    siz[u] = 1 ;
    son[u] = 0 ;
    for(int i = head[u] ;i != -1 ;i = E[i].next)
    {
        int v = E[i].v ;
        if(v == fa)  continue ;
        dfs_find(v ,u) ;
        siz[u] += siz[v] ;
        if(siz[son[u]] < siz[v])  son[u] = v ;
    }
}
void dfs_time(int u ,int fa)
{
    top[u] = fa ;
    ti[u] = idx++ ;
    if(son[u])   dfs_time(son[u] ,top[u]) ;
    for(int i = head[u] ;i != -1 ;i = E[i].next)
    {
        int v = E[i].v ;
        if(v == father[u] || v == son[u])  continue ;
        dfs_time(v ,v) ;
    }
}
struct node
{
    int le ,rt ,c ;
}T[MX*4] ;
void build(int i ,int le ,int rt)
{
    T[i].le = le ; T[i].rt = rt ;
    T[i].c = 0 ;
    if(le == rt)  return ;
    int Mid = (le + rt)>>1 ;
    build(L(i) ,le ,Mid) ;
    build(R(i) ,Mid+1 ,rt) ;
}
void update(int i ,int pos ,int w)
{
    if(T[i].le == T[i].rt)
    {
        T[i].c = w ;
        return ;
    }
    int Mid = (T[i].le + T[i].rt)>>1 ;
    if(pos <= Mid)   update(L(i) ,pos ,w) ;
    else     update(R(i) ,pos ,w) ;
    T[i].c = max(T[L(i)].c ,T[R(i)].c) ;
}
int section(int i ,int le ,int rt)
{
    if(T[i].le == le && T[i].rt == rt)
        return T[i].c ;
    int Mid = (T[i].le + T[i].rt)>>1 ;
    if(le > Mid)   return section(R(i) ,le ,rt) ;
    else if(rt <= Mid)  return section(L(i) ,le ,rt) ;
    else
          return max(section(L(i) ,le ,Mid) ,section(R(i) ,Mid+1 ,rt)) ;
}
int LCA(int u ,int v)
{
    int ans = 0 ;
    while(top[u] != top[v])
    {
        if(dep[top[u]] < dep[top[v]])
             swap(u ,v) ;
        ans = max(ans ,section(1 ,ti[top[u]] ,ti[u])) ;
        u = father[top[u]] ;
    }
    if(dep[u] > dep[v])  swap(u ,v) ;
    if(u != v)
        ans = max(ans ,section(1 ,ti[u]+1 ,ti[v])) ;
    return ans ;
}
int main()
{
    int u ,v ,Q ;
    bool first = false ;
    while(~scanf("%d%d" ,&n ,&m))
    {
        if(first) puts("") ;
        first = true ;
        num = 0 ;
        memset(head ,-1 ,sizeof(head)) ;
        for(int i = 0 ;i < m ; ++i)
           scanf("%d%d%d" ,&e[i].u ,&e[i].v ,&e[i].w) ;
        Kruskal() ;
        dep[1] = siz[0] = 0 ;
        dfs_find(1 ,1) ;
        idx = 1 ;
        dfs_time(1 ,1) ;
        build(1 ,1 ,n) ;
        for(int i = 1 ;i < nx ; ++i)
        {
            if(dep[t[i].u] < dep[t[i].v])
                swap(t[i].u ,t[i].v) ;
            update(1 ,ti[t[i].u] ,t[i].w) ;
        }
        scanf("%d" ,&Q) ;
        for(int i = 0 ;i < Q ; ++i)
        {
            scanf("%d%d" ,&u ,&v) ;
            printf("%d\n" ,LCA(u ,v)) ;
        }
    }
    return 0 ;
}

倍增法 (类似RMQ)

代码:

#include<iostream>
#include<sstream>
#include<map>
#include<cmath>
#include<fstream>
#include<queue>
#include<vector>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<bitset>
#include<ctime>
#include<string>
#include<cctype>
#include<iomanip>
#include<algorithm>
using namespace std  ;
#define INT long long int
#define L(x)  (x * 2)
#define R(x)  (x * 2 + 1)
const int INF = 0x3f3f3f3f ;
const double esp = 0.0000000001 ;
const double PI = acos(-1.0) ;
const int mod = 1000000007 ;
const int MY = (1<<5) + 5 ;
const int MX = 100000 + 5 ;
const int S = 20 ;
int n ,m ,idx ,num ,nx ;
int value[MX][25] ,p[MX][25] ,ti[MX] ,father[MX] ,dep[MX] ,head[MX] ;
struct TEMP
{
    int u ,v ,w ;
}A[MX] ;
struct Edge
{
    int v ,w ,next ;
}E[MX*2] ;
bool cmp(TEMP a ,TEMP b)
{
    return a.w < b.w ;
}
int find(int u)
{
    if(father[u] != u)
       return  find(father[u]) ;
    return u ;
}
void addedge(int u ,int v ,int w)
{
    E[num].v = v ; E[num].w = w ; E[num].next = head[u] ; head[u] = num++ ;
    E[num].v = u ; E[num].w = w ; E[num].next = head[v] ; head[v] = num++ ;
}
void Kruskal()
{
    nx = 1 ;
    int fa ,fb ;
    sort(A ,A+m ,cmp) ;
    for(int i = 0 ;i <= n ; ++i)
        father[i] = i ;
    for(int i = 0 ;i < m ; ++i)
    {
        fa = find(A[i].u) ;
        fb = find(A[i].v) ;
        if(fa != fb)
        {
            father[fa] = fb ;
            addedge(A[i].u ,A[i].v ,A[i].w) ;
        }
    }
}
void dfs_find(int u ,int fa ,int w)
{
    dep[u] = dep[fa] + 1 ;
    p[u][0] = fa ;
    value[u][0] = w ;
    for(int i = 1 ;i <= S ; ++i)
    {
        p[u][i] = p[p[u][i-1]][i-1] ;
        value[u][i] = max(value[u][i-1] ,value[p[u][i-1]][i-1]) ;
    }
    for(int i = head[u] ;i != -1 ;i = E[i].next)
    {
        int v = E[i].v ;
        if(v == fa)    continue ;
        dfs_find(v ,u ,E[i].w) ;
    }
}
int LCA(int u ,int v)
{
    int ans = 0 ;
    if(dep[u] > dep[v])  swap(u ,v) ;
    if(dep[u] < dep[v])
    {
        int d = dep[v] - dep[u] ;
        for(int i = 0 ;i <= S ; ++i)
          if(d&(1<<i))
          {
              ans = max(ans ,value[v][i]) ;
              v = p[v][i] ;
          }
    }
    if(u != v)
    {
        for(int i = S ;i >= 0 ; --i)
          if(p[u][i] != p[v][i])
          {
              ans = max(ans ,value[u][i]) ;
              ans = max(ans ,value[v][i]) ;
              u = p[u][i] ;
              v = p[v][i] ;
          }
        ans = max(ans ,value[u][0]) ;
        ans = max(ans ,value[v][0]) ;
    }
    return ans ;
}
void init()
{
    num = 0 ;
    memset(head ,-1 ,sizeof(head)) ;
    memset(ti ,0 ,sizeof(ti)) ;
    memset(value ,0 ,sizeof(value)) ;
    memset(p ,0 ,sizeof(p)) ;
    memset(dep ,0 ,sizeof(dep)) ;
}
int main()
{
    //freopen("input.txt" ,"r" ,stdin) ;
    int u ,v ,Q ;
    bool first = false ;
    while(~scanf("%d%d" ,&n ,&m))
    {
        if(first)  puts("") ;
        first = true ;
        init() ;
        for(int i = 0 ;i < m ; ++i)
           scanf("%d%d%d" ,&A[i].u ,&A[i].v ,&A[i].w) ;
        Kruskal() ;
        dep[1] = 0 ;
        dfs_find(1 ,1 ,0) ;
        scanf("%d" ,&Q) ;
        while(Q--)
        {
            scanf("%d%d" ,&u ,&v) ;
            printf("%d\n" ,LCA(u ,v)) ;
        }
    }
    return 0 ;
}

















 

<think>嗯,用户想了解关于NetworkManager绑定设备(nm-bond)的配置或问题。首先,我需要回忆NetworkManager中配置bonding的相关知识。记得bonding是将多个网络接口聚合为一个逻辑接口,提供冗余或提高带宽。NetworkManager支持通过nmcli或nmtui配置,可能需要用到不同的模式,比如balance-rr(mode 0)或者active-backup(mode 1)等。 然后,用户提供的引用里有几个相关的命令和配置片段,比如引用3和4提到了使用bonding.py脚本和modprobe命令加载bonding模块,设置不同的模式。这可能涉及到内核模块的加载和参数设置。在NetworkManager中,可能需要用nmcli来创建bond接口,并指定从属接口和模式。 接下来,我需要确保回答符合系统级指令的要求,比如行内数学公式用$...$,独立公式用$$...$$,虽然这里可能用不上数学公式,但要注意其他格式要求。使用中文回答,结构清晰,分步骤说明配置方法,并生成相关问题。 可能的问题包括:如何创建bond设备,如何选择模式,如何设置IP地址,以及常见问题如接口不启动或模式不生效。需要结合引用中的信息,比如引用4提到mode=0和mode=1,miimon参数,这些在配置时可能需要用到。此外,引用2中的启用或禁用多播可能在某些情况下相关。 还要注意用户提到的nm-bond,即使用NetworkManager而不是传统的配置文件(如/etc/network/interfaces),所以重放在nmcli命令上。例如,使用nmcli创建bond,添加从属接口,设置模式参数等。同时,需要指出常见问题排查步骤,比如检查日志,确认模块加载,从属接口状态等。 最后,生成的相关问题需要围绕bond配置的扩展,比如不同模式的区别、负载均衡配置、与VLAN的结合使用,以及故障排除方法。确保每个步骤都清晰,并且引用正确,比如引用中的配置示例可能需要标注引用标记。</think>### NetworkManager Bond设备配置指南 #### 一、基础配置步骤(使用nmcli) 1. **创建Bond接口** ```bash nmcli con add type bond con-name bond0 ifname bond0 bond.options "mode=802.3ad,miimon=100" ipv4.method manual ipv4.addresses 192.168.1.11/24 ``` - `mode=802.3ad`对应IEEE 802.3ad动态链路聚合[^3] - `miimon=100`表示每100ms检查链路状态[^4] 2. **添加从属接口** ```bash nmcli con add type bond-slave ifname eth0 master bond0 nmcli con add type bond-slave ifname eth1 master bond0 ``` 3. **激活配置** ```bash nmcli con up bond0 ``` #### 二、关键参数说明 | 参数 | 作用 | 示例值 | |------|------|--------| | mode | 绑定模式 | 802.3ad/active-backup | | primary | 主接口 | eth0[^4] | | miimon | 链路检测间隔 | 100ms | #### 三、常见问题排查 1. **接口未启动** ```bash journalctl -u NetworkManager -f # 查看实时日志 cat /proc/net/bonding/bond0 # 验证bond状态 ``` 2. **模式不生效** - 确认交换机配置匹配(如802.3ad需要LACP支持)[^1] - 检查内核模块加载:`lsmod | grep bonding` 3. **IP分配失败** ```bash nmcli device show bond0 # 检查IP配置 ip link set bond0 multicast on # 启用多播[^2] ``` #### 四、高级配置示例 ```bash nmcli con add type bond con-name bond1 ifname bond1 \ bond.options "mode=active-backup,primary=eth2,miimon=50" \ ipv4.gateway 192.168.1.1 ``` 此配置实现主备模式,eth2作为主接口
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Muti-Agent

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值