B - Networking

博客围绕设计网络连接问题展开,需使各点互连且电缆总长最小。输入包含点和路线信息,输出为设计网络的电缆总长度。这是最小生成树问题,可采用kruskal算法,运用并查集思想,对边排序后遍历合并,最终输出结果。

https://vjudge.net/contest/66965#problem/B

You are assigned to design network connections between certain points in a wide area. You are given a set of points in the area, and a set of possible routes for the cables that may connect pairs of points. For each possible route between two points, you are given the length of the cable that is needed to connect the points over that route. Note that there may exist many possible routes between two given points. It is assumed that the given possible routes connect (directly or indirectly) each two points in the area. 
Your task is to design the network for the area, so that there is a connection (direct or indirect) between every two points (i.e., all the points are interconnected, but not necessarily by a direct cable), and that the total length of the used cable is minimal.

Input

The input file consists of a number of data sets. Each data set defines one required network. The first line of the set contains two integers: the first defines the number P of the given points, and the second the number R of given routes between the points. The following R lines define the given routes between the points, each giving three integer numbers: the first two numbers identify the points, and the third gives the length of the route. The numbers are separated with white spaces. A data set giving only one number P=0 denotes the end of the input. The data sets are separated with an empty line. 
The maximal number of points is 50. The maximal length of a given route is 100. The number of possible routes is unlimited. The nodes are identified with integers between 1 and P (inclusive). The routes between two points i and j may be given as i j or as j i. 

Output

For each data set, print one number on a separate line that gives the total length of the cable used for the entire designed network.

Sample Input

1 0

 

2 3

1 2 37

2 1 17

1 2 68

 

3 7

1 2 19

2 3 11

3 1 7

1 3 5

2 3 89

3 1 91

1 2 32

 

5 7

1 2 5

2 3 7

2 4 8

4 5 11

3 5 10

1 5 6

4 2 12

 

0

Sample Output

0

17

16

26

思路:

这还是一道最小生成树的问题,我们可以用kruskal算法来写,即运用并查集的思想解决,我们先将所有的边存入结构体数组中,要存入起始点终点和权重,然后我们将结构体按权重从小到大排序,遍历所有边,如果这条边的两点的父节点不同,则合并成一个点,并把权重加入和中,否则则已合并成一个点,跳过。遍历完所有的边后,输出和即可。

代码

 

<think>我们面临的核心问题是:在已禁用sudo的计算机上(即无法使用sudo命令),如何执行需要特权的mysqld命令(--user=mysql --skip-grant-tables --skip-networking &)以重置MySQL 8.4.0的root密码。 分析: 1. 通常,mysqld需要以特定用户(如mysql)运行,并且需要绑定特权端口(3306),因此需要root权限。 2. 但sudo被禁用,意味着我们无法直接以root身份运行命令。 解决方案思路: 方案A:如果当前用户是root,则可以直接运行命令。 方案B:如果当前用户不是root,但具有运行mysqld的特殊权限(如通过setcap给mysqld设置能力),则可能无需sudo。 方案C:利用已有的MySQL服务管理方式(如systemctl)来设置环境变量,但需要当前用户有权限操作服务(通常也需要sudo)。 方案D:使用非特权端口启动MySQL,这样就不需要root权限。但是,MySQL默认使用3306(特权端口),我们可以修改端口为非特权端口(>1024)。然而,在密码重置过程中,我们通常希望阻止远程连接(使用--skip-networking),但使用非特权端口后,我们可以省略--skip-networking,因为非特权端口允许任意用户绑定,但为了安全,我们还是希望阻止网络连接,不过--skip-networking选项不需要特权。 然而,我们的目标命令中包含了--user=mysql,这要求我们能够切换用户(mysql),而切换用户通常需要sudo。因此,如果我们当前用户不是mysql,又不能使用sudo,那么无法以mysql用户身份启动。 因此,我们需要分情况考虑: 情况1:当前用户是root(虽然sudo被禁用,但我们可以已经是root用户) 这种情况下,我们可以直接运行命令: mysqld --user=mysql --skip-grant-tables --skip-networking & 情况2:当前用户是mysql(或者可以访问mysql用户的数据文件) 我们可以以当前用户(mysql)启动,无需切换用户: mysqld --skip-grant-tables --skip-networking & 情况3:当前用户既不是root也不是mysql,且无法使用sudo 这种情况下,通常无法完成操作,因为: a. 无法切换到mysql用户 b. 无法以root身份启动 但有一种可能:MySQL数据目录的权限允许当前用户读写(这种情况很少,因为MySQL数据目录通常只允许mysql用户访问)。如果数据目录权限允许,我们可以尝试以当前用户启动,但需要指定数据目录和socket等参数,并且要确保当前用户有权限启动。 然而,MySQL在启动时要求数据目录的拥有者必须是运行mysqld的用户。因此,如果我们当前用户不是mysql,而数据目录属于mysql,则启动会失败。 因此,我们必须以mysql用户运行mysqld。在无法使用sudo的情况下,我们只能: - 如果当前用户是root,则使用--user=mysql - 如果当前用户是mysql,则直接运行 - 否则,需要其他方式切换到mysql用户(例如,使用su命令,但su命令通常需要root权限或知道mysql用户的密码) 但题目中已禁用sudo,且我们忘记了root密码(但这里我们是要重置MySQL密码,所以系统root密码不一定忘记,但题目说禁用sudo,说明当前用户没有sudo权限,但不代表当前用户不是root)。 综上,我们假设当前用户可能是root,也可能是普通用户(无法提权)。 步骤: 1. 确认当前用户身份: 使用命令:`whoami` 或 `id -un` 2. 如果当前用户是root: 直接执行: mysqld --user=mysql --skip-grant-tables --skip-networking & 然后按照常规步骤重置密码。 3. 如果当前用户是mysql: 执行: mysqld --skip-grant-tables --skip-networking & 4. 如果当前用户既不是root也不是mysql: 我们需要尝试切换到mysql用户。但如果没有sudo,且不知道mysql用户的密码(因为mysql用户通常不允许直接登录),则无法切换。 替代方案:使用su切换到mysql用户(如果当前用户在mysql用户组且mysql用户允许登录?通常不允许)。所以,这几乎不可行。 另一种思路:修改MySQL数据目录的权限,使得当前用户可以运行mysqld(但存在安全风险,且可能破坏原有权限)。步骤如下: a. 停止正在运行的MySQL服务(如果有) 如果之前MySQL是作为服务运行的,我们需要停止它。但是由于没有sudo,我们可能无法通过systemctl停止服务。我们可以通过查找进程并杀死的方式: ps aux | grep mysqld kill -9 <mysqld进程号> 注意:确保没有其他MySQL实例在运行。 b. 更改MySQL数据目录的拥有者(需要root权限,但我们没有,所以此路不通) 因此,这种情况下,唯一的办法是联系系统管理员,或者使用root账号(如果知道系统root密码,可以直接登录root操作,但题目未提及)。 考虑到以上情况,我们重点解决当前用户是root或mysql的情况。 具体步骤(假设当前用户是root或mysql): 步骤1:停止正在运行的MySQL服务(避免端口冲突) 如果之前MySQL服务是通过系统服务运行的,我们需要停止它。但由于没有sudo,我们只能通过发送信号的方式停止。我们可以使用pkill(需要root权限)或查找进程并杀死。如果当前用户是root,可以: pkill mysqld 或者: killall mysqld 如果当前用户是mysql,则只能杀死自己拥有的进程: pkill -u mysql mysqld # 需要root权限?所以当前用户如果是mysql,则无法杀死其他mysql进程(如果多个进程) 因此,更安全的方法是先查看进程: ps aux | grep mysqld 然后根据进程号杀死: kill -9 <进程号> 注意:如果无法停止原有服务,则尝试启动新的mysqld实例会失败(因为端口占用或数据目录锁定)。 步骤2:启动MySQL无认证模式 根据当前用户身份: - 如果是root:mysqld --user=mysql --skip-grant-tables --skip-networking & - 如果是mysql:mysqld --skip-grant-tables --skip-networking & 注意:如果启动失败,检查错误日志(通常位于/var/log/mysql/error.log或数据目录下的hostname.err),根据错误调整。 步骤3:连接MySQL mysql -u root 步骤4:在MySQL中重置密码(注意MySQL 8.4.0的语法) FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY ''; -- 先设为空 FLUSH PRIVILEGES; exit; 步骤5:关闭无认证模式的MySQL实例 使用命令查找进程ID并杀死: ps aux | grep mysqld kill -9 <进程ID> 步骤6:正常启动MySQL服务(如果有服务脚本,但无法用sudo,所以我们可以用普通用户启动?) 如果之前是系统服务,我们可能需要恢复服务启动。但如果没有sudo,我们只能以当前用户启动(作为普通进程)。建议恢复原服务启动方式(如果可能)。 另一种做法:以正常模式启动MySQL(使用当前用户,但指定数据目录等): mysqld --user=mysql & # 如果是root 或者 mysqld & # 如果是mysql用户 但这样启动的MySQL可能和系统服务启动的配置不同。因此,最好是恢复系统服务。 不过,我们重置密码后,应该停止当前手动启动的实例,然后尝试启动系统服务(但如果没有sudo,可能无法启动系统服务)。这是一个矛盾点:系统服务通常需要root启动。 所以,如果我们没有sudo,我们可能只能以当前用户启动MySQL作为长期运行?这显然不适合生产环境。 因此,重置密码后,我们应该按照原来的方式启动MySQL。如果原来是通过系统服务启动的,而我们没有sudo,那么可能需要系统管理员介入来启动服务(或者使用其他途径获得sudo权限)。 总结: 在没有sudo的情况下,重置MySQL密码是可行的,但前提是当前用户是root或者是mysql用户。重置完成后,如果MySQL原来是以系统服务运行的,则需要系统管理员(或有sudo权限的用户)来重启服务。 步骤细节: 1. 停止原有MySQL进程(如果运行): 查看进程:`ps aux | grep mysqld` 杀死进程:`kill -9 <进程ID>` (对于多个进程,需要全部杀死) 2. 启动无认证模式: 如果当前用户是root: 执行:`mysqld --user=mysql --skip-grant-tables --skip-networking &` 如果当前用户是mysql: 执行:`mysqld --skip-grant-tables --skip-networking &` 3. 连接MySQL: mysql -u root 4. 重置密码: FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassword'; -- 注意:MySQL 8.4.0可能要求强密码,但可以先设置一个简单的,后续再调整 FLUSH PRIVILEGES; exit; 5. 停止无认证模式MySQL: 同样,通过ps找到进程并杀死。 6. 重新启动MySQL: 如果能够使用系统服务,则通过系统服务启动(需要sudo,所以不能则跳过)。否则,尝试用当前用户启动正常模式的MySQL: - 如果是root用户:`mysqld --user=mysql &` (然后可以使用mysql -u root -p登录) - 如果是mysql用户:`mysqld &` 注意:这样启动的MySQL是作为前台进程运行的,如果退出终端可能会停止。如果需要后台运行,可以配合nohup或screen。 7. 后续:建议联系管理员恢复系统服务启动,并确保MySQL服务随系统启动。 安全警告: 在无认证模式下启动MySQL时,一定要使用--skip-networking,否则任何远程用户都可以无密码登录。操作完成后,立即恢复正常模式。 引用用户提供的引用: 引用[3]中提到文件权限问题:如果操作过程中出现权限问题,需要检查数据目录的文件权限。例如,如果文件所属组不正确,可能导致启动失败。在启动前确保数据目录及其文件属于运行mysqld的用户(即当前用户)。 因此,在启动前,我们可以检查数据目录的权限: ls -l /var/lib/mysql # 默认数据目录 如果当前用户是root,但数据目录属于mysql,那么在启动时使用--user=mysql是没问题的。 如果当前用户是普通用户(非root、非mysql),并且试图启动,那么数据目录必须属于该用户,否则会报错。 如果遇到权限问题,参考引用[3]的方法调整文件所属用户(但需要root权限)。 综上所述,在已禁用sudo的计算机上,重置MySQL密码的可行性取决于当前用户的身份。如果当前用户是root或mysql,则可以完成;否则,需要寻求其他途径。 下面给出完整的步骤指南: </think>### 在禁用 `sudo` 的计算机上重置 MySQL 8.4.0 密码的解决方案 #### 1. **确认 MySQL 数据目录权限** ```bash ls -ld /var/lib/mysql # 默认数据目录 ``` - 确保当前用户对数据目录有**读写权限**(如属主是当前用户)[^3] - 若权限不足,尝试获取文件所有权(需系统管理员协助): ```bash chown -R $USER:$USER /var/lib/mysql ``` #### 2. **手动停止 MySQL 服务** ```bash pkill -f mysqld # 强制终止所有 MySQL 进程 ps aux | grep mysqld # 确认无 MySQL 进程残留 ``` #### 3. **以当前用户启动无认证模式** ```bash mysqld --datadir=/var/lib/mysql \ --skip-grant-tables \ --skip-networking \ --user=$USER & # 关键:使用当前用户身份 ``` > **参数说明**: > - `--datadir`:指定 MySQL 数据目录路径 > - `--user=$USER`:以当前用户身份运行(替代 `--user=mysql`) > - `&`:后台运行进程 #### 4. **连接 MySQL 并重置密码** ```bash mysql -u root ``` ```sql FLUSH PRIVILEGES; -- 清空 root 密码(适配 MySQL 8.4 认证插件) ALTER USER 'root'@'localhost' IDENTIFIED BY ''; FLUSH PRIVILEGES; EXIT; ``` #### 5. **重启 MySQL 并设置新密码** ```bash pkill -f mysqld # 停止无认证实例 mysqld --user=$USER & # 正常启动 mysql -u root -p # 密码为空直接回车 ``` ```sql -- 设置强密码(示例) ALTER USER 'root'@'localhost' IDENTIFIED BY 'New@Password123!'; ``` --- ### **关键问题解决方案** 1. **文件权限错误** - 现象:`ib_buffer_pool` 等文件属主错误 [^3] - 修复: ```bash find /var/lib/mysql -user root -exec chown $USER:$USER {} \; ``` 2. **端口冲突处理** ```bash netstat -tlnp | grep 3306 # 查看端口占用 kill -9 <占用进程PID> # 强制终止冲突进程 ``` 3. **认证协议错误** ```sql ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '密码'; ``` --- ### **安全操作指南** 1. 操作前备份数据目录: `cp -R /var/lib/mysql /backup/mysql_data_$(date +%F)` 2. 完成后恢复文件权限: ```bash chown -R mysql:mysql /var/lib/mysql ``` 3. 检测日志异常: `tail -f /var/log/mysql/error.log` > **注意**:此方法仅适用于当前用户对 MySQL 文件有所有权的情况。若系统存在强制访问控制(如 SELinux),需额外配置安全上下文[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值