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

类试题:noip2013 货物运输

POJ 1797 Heavy Transportation

方法一: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带你飞]专题四 最短路练习的更多相关文章

  1. [kuangbin带你飞]专题四 最短路练习

    对于最短路,我主要使用的就是dijkstra,Floyd,SPFA这三个算法.先来介绍一下这三个算法. 1. dijkstra算法.它适用于边权为正的情况,它是单源最短路,就是从单个源点出发到所有的结 ...

  2. [kuangbin带你飞]专题四 最短路练习 POJ 2253 Frogger

    求第一个点到第二个点的所有通路上最长的边 dijkstra的变形 每次松弛的是每条边通路上的的最长的边 WA了好几次是因为用了%lf 改成%f就过了…… /* ******************** ...

  3. 【算法系列学习】Dijkstra求最短路 [kuangbin带你飞]专题四 最短路练习 D - Silver Cow Party

    https://vjudge.net/contest/66569#problem/D trick:1~N各点到X可以通过转置变为X到1~N各点 #include<iostream> #in ...

  4. 【算法系列学习】Dijkstra单源最短路 [kuangbin带你飞]专题四 最短路练习 A - Til the Cows Come Home

    https://vjudge.net/contest/66569#problem/A http://blog.csdn.net/wangjian8006/article/details/7871889 ...

  5. 【算法系列学习】SPFA邻接表最短路 [kuangbin带你飞]专题四 最短路练习 F - Wormholes

    https://vjudge.net/contest/66569#problem/F 题意:判断图中是否存在负权回路 首先,介绍图的邻接表存储方式 数据结构:图的存储结构之邻接表 邻接表建图,类似于头 ...

  6. [kuangbin带你飞]专题四 最短路练习 POJ 3268 Silver Cow Party

    题意: 在一个有向图中求n头牛从自己的起点走到x再从x走回来的最远距离 思路一开始是暴力跑dij…… 讲道理不太可能…… 然后就百度了一下 才知道把矩阵转置的话就只需要求两次x的单源最短路…… /* ...

  7. [kuangbin带你飞]专题四 最短路练习 POJ 1797 Heavy Transportation

    求每条道路的最大承载量 和上一道题差不多 就是松弛的规则从最大值变成了最小值 /* *********************************************** Author :Su ...

  8. [ An Ac a Day ^_^ ] [kuangbin带你飞]专题四 最短路练习 POJ 2387 Til the Cows Come Home

    求1到N的最短路 注意有重边 跑一遍dijkstra就行 /* *********************************************** Author :Sun Yuefeng ...

  9. [kuangbin带你飞]专题四 最短路练习 G MPI Maelstrom

    #include<iostream> #include<cstring> #include<algorithm> #include<iomanip> # ...

随机推荐

  1. JavaScript原型模式-理解对象

    一:简述 当初学编程一看到什么什么模式就比较头晕,不过本文我们通过简单的示例代码来说一下js 对象这个话题 ,来看下如何理解这个原型模式. 二:理解对象 1.简单对象 js对象中没有java.C#等类 ...

  2. MyBatis 源码分析——映射结果

    MyBatis最后一步一定是处理相关的结果——把数据映射成对应的模型对象.事实上在笔者看来如果读者们了解了mybatis如何去执行数据库,又是如何处理数据结果.那么就了解了mybatis的主要路线.因 ...

  3. 基于HBase的手机数据备份系统 .

    基于HBase实现的手机数据备份系统,实现了手机关键信息的备份,如短信.联系人等. 包括服务器端(Server)和客户端(Client) Server运行环境:Hadoop+HBase+Tomcat ...

  4. (转)python中的*args和**kw到底是个啥。看下面的例子就会懂了

    先来看个例子: def foo(*args, **kwargs): print 'args = ', args print 'kwargs = ', kwargs print '----------- ...

  5. echo print print_r的区别

    echo       PHP语句   效率最高    输出一个或者多个字符串 print()    函数       效率高     只能打印出简单类型变量的值(如int,string) print_ ...

  6. AtCoder Beginner Contest 055题解

    A.当a=1就把a改成14,b=1就把b改成14,然后比较a,b大小即可. #include <iostream> #include <algorithm> #include ...

  7. Vijos1523贪吃的九头龙【树形DP】

    贪吃的九头龙 传说中的九头龙是一种特别贪吃的动物.虽然名字叫"九头龙",但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于九,当然也会有旧头 ...

  8. 【Android】沉浸式状态栏实现

    在Android4.4(API 19)及以后的版本中都增加了对沉浸式状态栏的支持,实现起来也很简单,将application的主题稍作修改即可: <style name="AppThe ...

  9. opencv构建高斯卷积核

    关于高斯核函数可以参见阮一峰老师的日志:高斯模糊的算法 如何使用高斯核进行高斯模糊可以参见我的另一篇日志:opencv构建自定义卷积 Mat Gaussian_kernal(int kernel_si ...

  10. 源码阅读之mongoengine(0)

    最近工作上用到了mongodb,之前只是草草了解了一下.对于NoSQL的了解也不是太多.所以想趁机多学习一下. 工作的项目直接用了pymongo来操作直接操作mongodb.对于用惯了Djongo O ...