【算法系列学习】Dijkstra算法变形 [kuangbin带你飞]专题四 最短路练习
https://vjudge.net/contest/66569#problem/B
类试题:noip2013 货物运输
方法一:Dijkstra变形
http://blog.csdn.net/u013446688/article/details/42777173
关键在于对松弛的变形,这里不是求源点到每个点的所有路径中的路径长度最小值,而是求源点到每个点的所有路径中Frog distance(路径中的最大距离)的最小值
所以dis[k]=min(dis[k],dis[v]+map[v][k])变成了dis[k]=min(dis[k],max(dis[v],map[v][k]))
这里的dis[k]不再是源点到结点k所有路径中路径长度的最小值,而是源点到结点k所有路径中Frog distance(路径中的最大距离)的最小值。
为了理解dis[k]=min(dis[k],max(dis[v],map[v][k])),我们可以做这样的假设:源点到v的路径有三条,这三条路径的frog distance分别是3,4,5;那么dis[v]就是3。
现在分两种情况分别进行讨论:
1.map[v][k]>dis[v],由于源点经过v到达k的路径也有三条,这三条的frog distance就分别变成了map[v][k],max(4,map[v][k]),max(5,map[v][k]);那么dis[k]就一定是最小值map[v][k].
2.map[v][k]<=dis[v],则这三条路径的frog distance 还是3,4,5.dis[k]就等于dis[v]
下面是AC的代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
const double inf=0x3f3f3f3f;
using namespace std;
int n;
struct node
{
int x,y;
}nd[];
double map[][];
double dist(node a,node b)
{
return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y));
}
double dis[];
void Dijkstra()
{
bool vis[];
memset(vis,,sizeof(vis));
dis[]=0.0;
for(int i=;i<=n;i++)
{
dis[i]=inf;
}
int v;
for(int i=;i<=n;i++)
{
int m=inf;
for(int k=;k<=n;k++)
{
if(!vis[k]&&dis[k]<m)
{
m=dis[k];
v=k;
}
}
vis[v]=;
//对以v为顶点的边进行松弛
for(int k=;k<=n;k++)
{
if(!vis[k])
{
dis[k]=min(dis[k],max(dis[v],map[v][k]));
}
}
}
}
int main()
{
int kas=;
while(scanf("%d",&n)&&n)
{
for(int i=;i<=n;i++)
{
scanf("%d%d",&nd[i].x,&nd[i].y);
for(int k=;k<i;k++)
{
map[i][k]=map[k][i]=dist(nd[i],nd[k]);
}
}
Dijkstra();
if(kas!=)
{
printf("\n");
}
printf("Scenario #%d\n",kas++);
printf("Frog Distance = %.3f\n",dis[]);
}
return ;
}
Dijkstra
要注意四点:
1.sqrt()要强制转化为double
2.double不能用memset(dis,inf,sizeof(dis))
3.
for(int k=1;k<=n;k++)
{
if(!vis[k])
{
dis[k]=min(dis[k],max(dis[v],map[v][k]));
}
}
不写vis[k]也对,但是增加时间复杂度
4.注意输入输出,最后一个样例之后是没有空行的
方法二:二分+并查集
http://xwk.iteye.com/blog/2129453
二分出一个mid值表示最大边的长度,然后遍历所有边,只要当前边的长度不超过mid,就合并当前边所连接的两个点。最后判断1和2在不在同一个连通分量上,如果是则说明当前mid已经足够,为了找到mid的最小值,R=mid.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath> using namespace std;
const int maxn=2e2+;
const double eps=1e-;
int n;
struct node
{
int x,y;
}nd[maxn];
double map[maxn][maxn];
double dist(const node& a,const node& b)
{
return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y));
}
int fa[maxn];
int find(int i)
{
if(fa[i]==-)
{
return i;
}
return fa[i]=find(fa[i]);
}
bool bind(int i,int k)
{
i=find(i);
k=find(k);
if(i!=k)
{
fa[i]=k;
}
return true;
}
bool ok(double mid)
{
memset(fa,-,sizeof(fa));
//加进去的边的最大值为mid
for(int i=;i<=n;i++)
{
for(int k=i+;k<=n;k++)
{
if(map[i][k]<mid)
{
bind(i,k);
}
}
}
return find()==find();
} int main()
{
int kas=;
while(scanf("%d",&n)&&n)
{
for(int i=;i<=n;i++)
{
scanf("%d%d",&nd[i].x,&nd[i].y);
for(int k=;k<i;k++)
{
map[i][k]=map[k][i]=dist(nd[i],nd[k]);
}
}
double l=0.0;
double r=map[][];
while(r-l>eps)
{
double mid=(l+r)/;
if(ok(mid))
{
r=mid;
}
else
{
l=mid;
}
}
if(kas!=)
{
printf("\n");
}
printf("Scenario #%d\n",kas++);
printf("Frog Distance = %.3f\n",r);
}
return ;
}
二分+并查集
注意在ok函数里,每次都要初始化memset(fa,-1,sizeof(fa));
方法三:最小生成树
http://blog.csdn.net/shouwang_tomorrow/article/details/47616983
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath> using namespace std;
int n;
int cnt;
const int maxn=2e4+; struct edge
{
int x,y;
double w;
}e[maxn];
struct node
{
int x;
int y;
}nd[];
double dist(const node& a,const node& b)
{
return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y));
}
bool cmp(const edge& a,const edge& b)
{
return a.w<b.w;
}
int fa[maxn];
int find(int i)
{
if(fa[i]==-)
{
return i;
}
return fa[i]=find(fa[i]);
}
bool bind(int i,int k)
{
i=find(i);
k=find(k);
if(i!=k)
{
fa[i]=k;
return true;
}
return false;
}
double Kruskal()
{
for(int i=;i<cnt;i++)
{
if(bind(e[i].x,e[i].y))
{
if(find()==find())
{
return e[i].w;
}
}
}
}
int main()
{
int kas=;
while(scanf("%d",&n)&&n)
{
cnt=;
for(int i=;i<=n;i++)
{
scanf("%d%d",&nd[i].x,&nd[i].y);
for(int k=;k<i;k++)
{
e[cnt].x=i;
e[cnt].y=k;
e[cnt++].w=dist(nd[i],nd[k]);
}
}
sort(e,e+cnt,cmp);
memset(fa,-,sizeof(fa));
double ans=Kruskal();
if(kas!=)
{
printf("\n");
}
printf("Scenario #%d\nFrog Distance = %.3f\n",kas++,ans);
}
return ;
}
Kruskal
【算法系列学习】Dijkstra算法变形 [kuangbin带你飞]专题四 最短路练习的更多相关文章
- [kuangbin带你飞]专题四 最短路练习
对于最短路,我主要使用的就是dijkstra,Floyd,SPFA这三个算法.先来介绍一下这三个算法. 1. dijkstra算法.它适用于边权为正的情况,它是单源最短路,就是从单个源点出发到所有的结 ...
- [kuangbin带你飞]专题四 最短路练习 POJ 2253 Frogger
求第一个点到第二个点的所有通路上最长的边 dijkstra的变形 每次松弛的是每条边通路上的的最长的边 WA了好几次是因为用了%lf 改成%f就过了…… /* ******************** ...
- 【算法系列学习】Dijkstra求最短路 [kuangbin带你飞]专题四 最短路练习 D - Silver Cow Party
https://vjudge.net/contest/66569#problem/D trick:1~N各点到X可以通过转置变为X到1~N各点 #include<iostream> #in ...
- 【算法系列学习】Dijkstra单源最短路 [kuangbin带你飞]专题四 最短路练习 A - Til the Cows Come Home
https://vjudge.net/contest/66569#problem/A http://blog.csdn.net/wangjian8006/article/details/7871889 ...
- 【算法系列学习】SPFA邻接表最短路 [kuangbin带你飞]专题四 最短路练习 F - Wormholes
https://vjudge.net/contest/66569#problem/F 题意:判断图中是否存在负权回路 首先,介绍图的邻接表存储方式 数据结构:图的存储结构之邻接表 邻接表建图,类似于头 ...
- [kuangbin带你飞]专题四 最短路练习 POJ 3268 Silver Cow Party
题意: 在一个有向图中求n头牛从自己的起点走到x再从x走回来的最远距离 思路一开始是暴力跑dij…… 讲道理不太可能…… 然后就百度了一下 才知道把矩阵转置的话就只需要求两次x的单源最短路…… /* ...
- [kuangbin带你飞]专题四 最短路练习 POJ 1797 Heavy Transportation
求每条道路的最大承载量 和上一道题差不多 就是松弛的规则从最大值变成了最小值 /* *********************************************** Author :Su ...
- [ An Ac a Day ^_^ ] [kuangbin带你飞]专题四 最短路练习 POJ 2387 Til the Cows Come Home
求1到N的最短路 注意有重边 跑一遍dijkstra就行 /* *********************************************** Author :Sun Yuefeng ...
- [kuangbin带你飞]专题四 最短路练习 G MPI Maelstrom
#include<iostream> #include<cstring> #include<algorithm> #include<iomanip> # ...
随机推荐
- Java数据类型及其转换&&经常用到的快捷键
数据类型 基本数据类型分类 (8种) byte .short. int. long. char. float. double .boolean 1个字节占8位 整数型byte 1字节 -128~1 ...
- delphi处理消息的几种方式
第一种:自定义处理单条消息 unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, C ...
- java学习(一)静态代码块 构造代码块 构造方法的执行顺序及注意问题
今天我总结了一下java中静态代码块 构造代码块 构造方法的执行顺序及其注意问题 首先要知道静态代码块是随着类的加载而加载,而构造代码块和构造方法都是随着对象的创建而加载 当时做了这么一个小案例(想必 ...
- c#XML操作类的方法总结
using System.Xml;using System.Data; namespace DotNet.Utilities{ /// <summary> /// Xml的操作 ...
- LVS的原理介绍
DR模式 LVS 的VIP 和 realserver 必须在同一个网段,不然广播后所有的包都会丢掉: 提前确认LVS/硬件LB 是什么模式,是否需要在同一个网段 所有的realserver 都必须绑 ...
- Windows上安装Kafka需要注意的几点
1.不能安装在有空格的路径上 比如:D:\Program Files 2.设置日志路径时,要用"/",不能用Windows上的"\",比如: # A comma ...
- 2017年要学习的JavaScript的顶级框架和主题
JavaScript的流行促进了一个非常活跃的由相关技术,框架和库组成的生态圈的发展.整个生态圈的多样性和活跃性越来越强,这让许多人变得越来越困惑. 你应该了解些什么技术呢? 我们应该将时间花费在 ...
- js,jq获取元素位置属性及兼容性写法
网页被卷起来的高度/宽度 document.documentElement.scrolltop //火狐 和 其他浏览器 document.body.scrolltop //ie,谷歌浏览器和没有 ...
- Unity - 通过降低精度减少动画文件的大小
Animation是Unity中的动画文件,主要内容由一个个关键帧数据构成.通过将Unity的资源序列化方式调整为Text,就可以以文本方式查看动画文件.通过菜单项Edit -> Project ...
- trigger和triggerhandler的区别
1. trigger会触发默认行为2. trigger会触发所有元素的模拟事件,而triggerHandler只触发一次3. trigger可以链式操作,triggerHandler不能4. trig ...