Bandwidth

Given a graph (V,E) where V is a set of nodes and E is a set of arcs in VxV, and an ordering on the elements in V, then the bandwidth of a node v is defined as the maximum distance in the ordering between v and any node to which it is connected in the graph. The bandwidth of the ordering is then defined as the maximum of the individual bandwidths. For example, consider the following graph:

picture25

This can be ordered in many ways, two of which are illustrated below:

picture47

For these orderings, the bandwidths of the nodes (in order) are 6, 6, 1, 4, 1, 1, 6, 6 giving an ordering bandwidth of 6, and 5, 3, 1, 4, 3, 5, 1, 4 giving an ordering bandwidth of 5.

Write a program that will find the ordering of a graph that minimises the bandwidth.

Input

Input will consist of a series of graphs. Each graph will appear on a line by itself. The entire file will be terminated by a line consisting of a single #. For each graph, the input will consist of a series of records separated by `;'. Each record will consist of a node name (a single upper case character in the the range `A' to `Z'), followed by a `:' and at least one of its neighbours. The graph will contain no more than 8 nodes.

Output

Output will consist of one line for each graph, listing the ordering of the nodes followed by an arrow (->) and the bandwidth for that ordering. All items must be separated from their neighbours by exactly one space. If more than one ordering produces the same bandwidth, then choose the smallest in lexicographic ordering, that is the one that would appear first in an alphabetic listing.

Sample input

A:FB;B:GC;D:GC;F:AGH;E:HD
#

Sample output

A B C F G D H E -> 3

题意:全排列的一道题。题中给出每一个点相邻的点;A相邻得点就是F、B;然后每一次全排列后。找出相邻点的距离,选出一个最大值;然后在这些最大值中找出一个最小值;

# include <cstdio>
# include <vector>
# include <cstring>
# include <algorithm>
# include <iostream>
using namespace std;

int id[256],letter[30];

int main()
{
    char c[1000];
    while(scanf("%s",c)!=EOF&&c[0]!='#')
    {
        int i,j,p,q,n=0;
        for(char x='A';x<='Z';x++)
            if(strchr(c,x)!=NULL)
            {
                id[x] = n++;    //给字母编号;
                letter[id[x]] = x;    //储存编号所对应的字母;
            }
        int len=strlen(c);
        p=q=0;
        vector < int > u,v;
        for(;;)     //将对应关系用两个数组表示;
        {
            while(p<len&&c[p]!=':')    p++;
            if(p==len)    break;
            while(q<len&&c[q]!=';')    q++;
            for(i=p+1;i<q;i++)
            {
                u.push_back(id[c[p-1]]);
                v.push_back(id[c[i]]);
            }
            p++;q++;
        }
        int pos[10],P[10],bestp[10],ans=n;

        for(i = 0; i < n; i++) P[i] = i;   //储存字母下标;
        do
        {
            for(i = 0; i < n; i++) pos[P[i]] = i; // 每个字母的位置

            int bandwidth=0;
            for(i=0;i<u.size();i++)    //求出最长距离;
                bandwidth=max(bandwidth,abs(pos[u[i]]-pos[v[i]]));
            if(bandwidth<ans)
            {
                ans=bandwidth;
                memcpy(bestp,P,sizeof(P));
            }
        }
        while(next_permutation(P,P+n));//全排列;调用函数;可以自动全排列;

        for(i = 0; i < n; i++) printf("%c ", letter[bestp[i]]);
            printf("-> %d\n", ans);
    }
    return 0;
}
#!/usr/bin/env python3 import subprocess import time import datetime import threading import os import signal import re ############################################################################### # 可配置参数 - 请根据需要修改 # ############################################################################### # 网络接口名称 INTERFACE = "ens33" # 网络限制参数 BANDWIDTH_LIMIT = "1000kbit" # 带宽限制,如: "3mbit", "5mbit", "1mbit" LATENCY = "0ms" # 网络延迟,默认0ms PACKET_LOSS = "0%" # 丢包率,默认0% # 突发流量配置 USE_BURST = False # 是否启用突发流量控制,默认不启用 # 如果启用突发流量控制,设置以下参数: BURST_SIZE = "64kbit" # 突发流量大小,推荐值为带宽的2-3% # 动态带宽配置 DYNAMIC_BANDWIDTH = False # 是否启用动态带宽变化,默认不启用 if DYNAMIC_BANDWIDTH == True: EXPERIMENT_DURATION = 440 # 实验持续时间(秒) else: EXPERIMENT_DURATION = 240 # 实验持续时间(秒) CHANGE_INTERVAL = 60 # 带宽变化间隔(秒) # 自定义带宽序列 (单位: kbps) BANDWIDTH_SEQUENCE = [1800, 2300, 2000, 2500, 2500, 3000, 2600] # 实验参数 LOG_FILE_PATH = "/home/banqilu/code/razor_test/razor-master/sim_test/sim_sender/bandwidth.log" SEND_PROGRAM_PATH = "/home/banqilu/code/razor_test/razor-master/sim_test/sim_sender/send" ############################################################################### # 脚本主逻辑 - 无需修改 # ############################################################################### class NetworkLimiter: def __init__(self): self.interface = INTERFACE self.log_file = LOG_FILE_PATH self.send_process = None self.monitor_running = False self.bandwidth_change_running = False self.monitor_start_time = 0 # 将带宽限制转换为kbps用于日志记录 self.initial_bandwidth_kbps = self.convert_bandwidth_to_kbps(BANDWIDTH_LIMIT) self.current_bandwidth_kbps = self.initial_bandwidth_kbps self.current_bandwidth_str = BANDWIDTH_LIMIT # 带宽序列索引 self.sequence_index = 0 def convert_bandwidth_to_kbps(self, bandwidth_str): """将带宽字符串转换为kbps数值""" match = re.match(r'(\d+)(kbit|mbit)', bandwidth_str.lower()) if match: value = int(match.group(1)) unit = match.group(2) if unit == "mbit": return value * 1000 # 转换为kbps else: return value return 3000 # 默认值,如果解析失败 def convert_kbps_to_str(self, kbps): """将kbps数值转换为带宽字符串""" if kbps >= 1000: return f"{kbps/1000:.1f}mbit" else: return f"{int(kbps)}kbit" def validate_parameters(self): """验证参数有效性""" if USE_BURST: # 检查burst是否设置为0 burst_match = re.match(r'(\d+)(kbit|mbit|bit)', BURST_SIZE.lower()) if burst_match: value = int(burst_match.group(1)) unit = burst_match.group(2) if value == 0: print("错误: burst参数不能设置为0!") print("建议设置为至少8kbit") return False # 检查burst是否过小 bandwidth_match = re.match(r'(\d+)(kbit|mbit|bit)', BANDWIDTH_LIMIT.lower()) if bandwidth_match: bw_value = int(bandwidth_match.group(1)) bw_unit = bandwidth_match.group(2) # 转换为kbit进行比较 if bw_unit == "mbit": bw_value_kbit = bw_value * 1000 else: bw_value_kbit = bw_value if unit == "mbit": burst_value_kbit = value * 1000 else: burst_value_kbit = value # 如果burst小于带宽的0.5%,给出警告 if burst_value_kbit < bw_value_kbit * 0.005: print(f"警告: burst值({BURST_SIZE})可能过小,建议至少为带宽的1%") print(f"当前带宽: {BANDWIDTH_LIMIT}, 建议burst: {max(8, int(bw_value_kbit * 0.01))}kbit") return True def setup_network_limits(self): """设置网络限制""" # 先验证参数 if not self.validate_parameters(): return False try: print(f"设置网络限制:") print(f" - 接口: {self.interface}") print(f" - bandwidth: {self.current_bandwidth_str}") print(f" - delay: {LATENCY}") print(f" - loss: {PACKET_LOSS}") print(f" - 突发流量控制: {'启用' if USE_BURST else '禁用'}") if USE_BURST: print(f" - burst: {BURST_SIZE}") print(f" - 动态带宽变化: {'启用' if DYNAMIC_BANDWIDTH else '禁用'}") # 清除现有规则 self.run_tc_command(["qdisc", "del", "dev", self.interface, "root"], ignore_errors=True) # 设置HTB队列和带宽限制 self.run_tc_command(["qdisc", "add", "dev", self.interface, "root", "handle", "1:", "htb", "default", "10"]) # 根据是否启用burst参数来构建命令 if USE_BURST: self.run_tc_command(["class", "add", "dev", self.interface, "parent", "1:", "classid", "1:1", "htb", "rate", self.current_bandwidth_str, "ceil", self.current_bandwidth_str, "burst", BURST_SIZE]) self.run_tc_command(["class", "add", "dev", self.interface, "parent", "1:1", "classid", "1:10", "htb", "rate", self.current_bandwidth_str, "ceil", self.current_bandwidth_str, "burst", BURST_SIZE]) else: self.run_tc_command(["class", "add", "dev", self.interface, "parent", "1:", "classid", "1:1", "htb", "rate", self.current_bandwidth_str, "ceil", self.current_bandwidth_str]) self.run_tc_command(["class", "add", "dev", self.interface, "parent", "1:1", "classid", "1:10", "htb", "rate", self.current_bandwidth_str, "ceil", self.current_bandwidth_str]) # 添加延迟和丢包率限制 if LATENCY != "0ms" or PACKET_LOSS != "0%": netem_args = ["qdisc", "add", "dev", self.interface, "parent", "1:10", "handle", "10:", "netem"] if LATENCY != "0ms": netem_args.extend(["delay", LATENCY]) if PACKET_LOSS != "0%": netem_args.extend(["loss", PACKET_LOSS]) self.run_tc_command(netem_args) print("网络限制设置成功") return True except Exception as e: print(f"设置网络限制失败: {e}") return False def change_bandwidth(self): """动态改变带宽限制 - 使用预定义序列""" try: # 从序列中获取下一个带宽值 if self.sequence_index < len(BANDWIDTH_SEQUENCE): new_bandwidth_kbps = BANDWIDTH_SEQUENCE[self.sequence_index] self.sequence_index += 1 # 转换为字符串格式 new_bandwidth_str = self.convert_kbps_to_str(new_bandwidth_kbps) print(f"动态改变带宽: {self.current_bandwidth_kbps}kbps -> {new_bandwidth_kbps}kbps") # 更新当前带宽 self.current_bandwidth_kbps = new_bandwidth_kbps self.current_bandwidth_str = new_bandwidth_str # 重新设置网络限制 self.setup_network_limits() else: # 序列用完后,重置索引 self.sequence_index = 0 print("带宽序列已用完,重新开始") self.change_bandwidth() # 递归调用以使用第一个值 except Exception as e: print(f"改变带宽失败: {e}") def bandwidth_change_worker(self): """带宽变化工作线程""" while self.bandwidth_change_running: try: time.sleep(CHANGE_INTERVAL) if self.bandwidth_change_running: self.change_bandwidth() except Exception as e: print(f"带宽变化工作线程错误: {e}") def remove_network_limits(self): """移除网络限制""" try: self.run_tc_command(["qdisc", "del", "dev", self.interface, "root"], ignore_errors=True) print("网络限制已移除") return True except Exception as e: print(f"移除网络限制失败: {e}") return False def run_tc_command(self, args, ignore_errors=False): """运行tc命令""" cmd = ["sudo", "tc"] + args result = subprocess.run(cmd, capture_output=True, text=True) if not ignore_errors and result.returncode != 0: raise Exception(f"tc命令执行失败: {result.stderr}") return result def bandwidth_monitor(self): """带宽监控线程 - 只记录设定的带宽限制值""" self.monitor_start_time = time.time() # 确保日志目录存在 os.makedirs(os.path.dirname(self.log_file), exist_ok=True) # 初始化日志文件 with open(self.log_file, 'w') as f: f.write(f"# 带宽监控开始时间: {datetime.datetime.now()}\n") f.write(f"# 接口: {self.interface}\n") f.write(f"# bandwidth: {BANDWIDTH_LIMIT}\n") f.write(f"# delay: {LATENCY}, loss: {PACKET_LOSS}\n") if USE_BURST: f.write(f"# burst: {BURST_SIZE}\n") else: f.write(f"# burst: no\n") f.write(f"# 动态带宽变化: {'启用' if DYNAMIC_BANDWIDTH else '禁用'}\n") if DYNAMIC_BANDWIDTH: f.write(f"# 变化间隔: {CHANGE_INTERVAL}秒\n") f.write(f"# 带宽序列: {BANDWIDTH_SEQUENCE}\n") f.write(f"# 实验持续时间: {EXPERIMENT_DURATION}秒\n") f.write(f"# 注意: 记录的是设定的带宽限制值,不是实际使用带宽\n\n") while self.monitor_running: try: time.sleep(0.01) # 记录设定的带宽限制值 timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] log_line = f"{timestamp} bandwidth={self.current_bandwidth_kbps:.2f}kbps" # 写入日志文件 with open(self.log_file, 'a') as f: f.write(log_line + '\n') except Exception as e: # 错误信息仍然打印到终端,便于调试 print(f"带宽监控错误: {e}") time.sleep(0.1) def run_send_program(self): """运行send程序""" if not os.path.exists(SEND_PROGRAM_PATH): print(f"错误: send程序不存在于 {SEND_PROGRAM_PATH}") return False try: # 确保程序有执行权限 os.chmod(SEND_PROGRAM_PATH, 0o755) print(f"启动send程序: {SEND_PROGRAM_PATH}") self.send_process = subprocess.Popen( [SEND_PROGRAM_PATH], stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid # 创建新的进程组 ) return True except Exception as e: print(f"启动send程序失败: {e}") return False def stop_send_program(self): """停止send程序""" if self.send_process: try: # 发送SIGTERM信号给进程组 os.killpg(os.getpgid(self.send_process.pid), signal.SIGTERM) print("已发送停止信号给send程序") # 等待程序结束 timeout = 10 # 10秒超时 try: self.send_process.wait(timeout=timeout) print("send程序已正常结束") except subprocess.TimeoutExpired: print("send程序未在超时时间内结束,强制终止") os.killpg(os.getpgid(self.send_process.pid), signal.SIGKILL) self.send_process.wait() except Exception as e: print(f"停止send程序时出错: {e}") def run_experiment(self): """运行完整的实验""" print("=" * 60) print("开始网络限制实验") print("=" * 60) print(f"实验配置:") print(f" - 网络接口: {INTERFACE}") print(f" - 初始带宽限制: {BANDWIDTH_LIMIT}") print(f" - 网络延迟: {LATENCY}") print(f" - 丢包率: {PACKET_LOSS}") print(f" - 突发流量控制: {'启用' if USE_BURST else '禁用'}") print(f" - 动态带宽变化: {'启用' if DYNAMIC_BANDWIDTH else '禁用'}") if DYNAMIC_BANDWIDTH: print(f" - 变化间隔: {CHANGE_INTERVAL}秒") print(f" - 带宽序列: {BANDWIDTH_SEQUENCE}") print(f" - 持续时间: {EXPERIMENT_DURATION}秒") print(f" - 日志文件: {LOG_FILE_PATH}") print(f" - 测试程序: {SEND_PROGRAM_PATH}") print("=" * 60) try: # 1. 设置网络限制 if not self.setup_network_limits(): return False # 2. 启动带宽监控 self.monitor_running = True monitor_thread = threading.Thread(target=self.bandwidth_monitor) monitor_thread.daemon = True monitor_thread.start() # 3. 如果启用动态带宽,启动带宽变化线程 if DYNAMIC_BANDWIDTH: self.bandwidth_change_running = True bandwidth_change_thread = threading.Thread(target=self.bandwidth_change_worker) bandwidth_change_thread.daemon = True bandwidth_change_thread.start() # 4. 等待1秒后启动send程序 print("等待1秒后启动send程序...") time.sleep(1) # 5. 启动send程序 if not self.run_send_program(): self.monitor_running = False self.bandwidth_change_running = False self.remove_network_limits() return False # 6. 等待指定时间 print(f"实验运行中,将在{EXPERIMENT_DURATION}秒后结束...") # 显示进度 - 每5秒更新一次 for i in range(EXPERIMENT_DURATION): if not self.monitor_running: break if i % 5 == 0: # 每5秒显示一次进度 print(f"已运行 {i} 秒,剩余 {EXPERIMENT_DURATION - i} 秒") time.sleep(1) # 7. 停止监控和带宽变化 self.monitor_running = False self.bandwidth_change_running = False monitor_thread.join(timeout=5) # 8. 停止send程序 self.stop_send_program() # 9. 移除网络限制 self.remove_network_limits() print("=" * 60) print("实验完成") print(f"带宽日志已保存到: {self.log_file}") print("=" * 60) return True except KeyboardInterrupt: print("\n用户中断实验") self.monitor_running = False self.bandwidth_change_running = False self.stop_send_program() self.remove_network_limits() return False except Exception as e: print(f"实验执行出错: {e}") self.monitor_running = False self.bandwidth_change_running = False self.stop_send_program() self.remove_network_limits() return False def main(): # 显示当前配置 print("当前实验配置:") print(f" 初始带宽限制: {BANDWIDTH_LIMIT}") print(f" 网络延迟: {LATENCY}") print(f" 丢包率: {PACKET_LOSS}") print(f" 突发流量控制: {'启用' if USE_BURST else '禁用'}") print(f" 动态带宽变化: {'启用' if DYNAMIC_BANDWIDTH else '禁用'}") if DYNAMIC_BANDWIDTH: print(f" 变化间隔: {CHANGE_INTERVAL}秒") print(f" 带宽序列: {BANDWIDTH_SEQUENCE}") print(f" 持续时间: {EXPERIMENT_DURATION}秒") # 确认是否继续 response = input("是否开始实验? (y/N): ") if response.lower() not in ['y', 'yes']: print("实验已取消") return # 创建网络限制器实例并运行实验 limiter = NetworkLimiter() success = limiter.run_experiment() if success: print("实验成功完成") else: print("实验执行失败") exit(1) if __name__ == "__main__": main() 修改代码,新增jitter参数设置
最新发布
11-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值