博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Telephone Lines 电话线
阅读量:6518 次
发布时间:2019-06-24

本文共 2375 字,大约阅读时间需要 7 分钟。

题目大意:

在一个无向图中找出一条1到n的路径,我们可以选择K条边使其权值变为0,我们的目的是使得路径上第K+1大的边最小

解题思路:

解法一:

我们用dp的思想

dis[x][p]表示1到x中已经指定p条边权值为0,我们用SPFA对其进行转移,也就是说我们会从dis[x][p]中转移出两个状态:dis[y][p] 和 dis[y][p+1]
怎么转移?
因为dis[y][p]表示的是1到y中已经指定p条边权值为0因为dis[y][p]表示的是1到y中已经指定p条边权值为0dis[y][p]1yp0
所以我们可以得出dis[y][p]=min(dis[y][p],max(dis[x][p],len[i]))所以我们可以得出dis[y][p] = min(dis[y][p], max(dis[x][p], len[i]))dis[y][p]=min(dis[y][p],max(dis[x][p],len[i]))
同理同理
dis[y][p+1]=min(dis[y][p+1],dis[x][p]);dis[y][p+1] = min(dis[y][p+1], dis[x][p]);dis[y][p+1]=min(dis[y][p+1],dis[x][p]);
当然,因为我们每个满足条件的点都是需要入栈的
所以我们并不能用min,我们需要用if去判断
上面只是为了方便

解法二:

因为我最近专攻最短路,所以就不细讲

主要思路:二分+spfa
将问题转换为是否存在一条合法的路径,使得花费不超过mid
这样我们只需要把花费大于mid的边看做长度为1的边,把花费不超过mid的边看做长度为0的边,然后求1到N的最短路是否不超过K即可。可以用双端队列BFS求解这种边全只有0&1的最短路问题
加粗部分摘自《算法竞赛进阶指南》(李煜东)

Accepted code:

#include
#include
#include
#define rri register intusing namespace std;const int inf = 1e9;const int N = 1005;const int P = 10005; struct edge {
int to, d, next;}e[P<<1];struct dp {
int from, p; dp(int x, int y) {
from = x; p = y; } void change(int x, int y) {
from = x; p = y; }};int cnt, n, p, k, x, y, w;int dis[N][P], v[N][P], last[N];inline void add(int x, int y, int w) {
e[++cnt].to = y; e[cnt].d = w; e[cnt].next = last[x]; last[x] = cnt; e[++cnt].to = x; e[cnt].d = w; e[cnt].next = last[y]; last[y] = cnt;}void spfa() {
for (rri i = 0; i <= n; i++) for (rri j = 0; j <= p; j++) dis[i][j] = inf, v[i][j] = 0; dp a(1, 0); queue
q; q.push(a); v[1][0] = 1; dis[1][0] = 0; while (!q.empty()) {
a = q.front(); q.pop(); int x = a.from, pn = a.p; v[x][pn] = 0; for (rri i = last[x]; i; i = e[i].next) {
int y = e[i].to; if (max(e[i].d, dis[x][pn]) < dis[y][pn]) {
dis[y][pn] = max(e[i].d, dis[x][pn]); if (!v[y][pn]) {
v[y][pn] = 1; a.change(y, pn); q.push(a); } } if (pn < k && dis[x][pn] < dis[y][pn+1]) {
dis[y][pn+1] = dis[x][pn]; if (!v[y][pn+1]) {
v[y][pn+1] = 1; a.change(y, pn+1); q.push(a); } } } }}int main() {
scanf("%d %d %d", &n, &p, &k); for (rri i = 1; i <= p; i++) scanf("%d %d %d", &x, &y, &w), add(x, y, w); spfa(); if (dis[n][k] == inf) printf("-1\n"); else printf("%d\n", dis[n][k]);}

转载于:https://www.cnblogs.com/Juruo-HJQ/p/10123526.html

你可能感兴趣的文章
执行可运行jar包时读取jar包中的文件
查看>>
linux下ExtMail邮件使用及管理平台
查看>>
马哥linux课后作业2
查看>>
linux中iptables设置自建dns服务器的端口
查看>>
常见的正则表达式
查看>>
TP5+PHPexcel导入xls,xlsx文件读取数据
查看>>
五花八门的计算机语言
查看>>
基于Yum安装zabbix3.0
查看>>
Web开发(进阶)- Django【进阶篇】
查看>>
Master-work模式
查看>>
5.7. 保护 Sendmail 的安全
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
Vmware Vcenter6.0 全新安装及群集配置介绍
查看>>
我的友情链接
查看>>
stomp-php
查看>>
Mysql慢查询日志脚本
查看>>
python字典生成式
查看>>
WampServer下Apache配置vHost
查看>>
IOS 开发证书设置
查看>>