http://acm.hdu.edu.cn/showproblem.php?pid=2066

一个人的旅行

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 36107    Accepted Submission(s): 12313

Problem Description
虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,还可以看美丽的风景……草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,去北京探望孟姜女……眼看寒假就快到了,这么一大段时间,可不能浪费啊,一定要给自己好好的放个假,可是也不能荒废了训练啊,所以草儿决定在要在最短的时间去一个自己想去的地方!因为草儿的家在一个小镇上,没有火车经过,所以她只能去邻近的城市坐火车(好可怜啊~)。
 
Input
输入数据有多组,每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个;
接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
接着的第T+1行有S个数,表示和草儿家相连的城市;
接着的第T+2行有D个数,表示草儿想去地方。
 
Output
输出草儿能去某个喜欢的城市的最短时间。
 
Sample Input
6 2 3
1 3 5
1 4 7
2 8 12
3 8 4
4 9 12
9 10 2
1 2
8 9 10
 
Sample Output
9
 
题意:

给你一些通路,告诉你通过这些通路所需的时间。

给你一些起点,一些终点。

求从任意一起点,到任意一终点,所需的最短时间

分析:多起点多终点最短路径问题
 

 法一:

多次使用经典dijkstra单源最短路径算法(求一起点,到其他所有点的最短路径,找所有终点中最小花费。依次操作完每个起点。。。)

#include<stdio.h>
#include<string.h>
#define inf 0x3f3f3f3f
int map1[][],dis[],visit[];///map1[][]存储所有边,
///dis[]存储第一个点到第i个点的路径长度,visit[]存储各点的访问状态
int start[],end1[];
const int n=;
void dijstra(int s1)
{
int i,j,pos=,min1;
memset(visit,,sizeof(visit));
for(i=;i<=n;++i)
{
dis[i]=map1[s1][i];///第一个点到其他所有点的距离
}
visit[s1]=;
dis[s1]=;
for(i=;i<n;i++)///剩余n-1个点,广度优先,依次求取距离原点的 最短路径长度
{
min1=inf;
for(j=;j<=n;++j)
{
if(!visit[j]&&min1>dis[j])
{
min1=dis[j];
pos=j;
}
}///找到最小dis值 visit[pos]=;
for(j=;j<=n;++j)
{
if(!visit[j]&&dis[j]>dis[pos]+map1[pos][j])///1->j的距离是否可通过i->pos->j距离更短?
dis[j]=dis[pos]+map1[pos][j];
}
}
}
int main()
{
int i,j;
int t,s,d;
while(~scanf("%d%d%d",&t,&s,&d)&&t)
{
for(i=;i<=;++i)
{
for(j=;j<=;++j)
{
map1[i][j]=inf;
}
}
int a,b,c;
for(i=;i<=t;++i)///输入两点+权值
{
scanf("%d%d%d",&a,&b,&c);
if(c<map1[a][b])
map1[a][b]=map1[b][a]=c;///无向边
}
for(int i=;i<s;i++)
{
scanf("%d",&start[i]);
}
for(int i=;i<d;i++)
{
scanf("%d",&end1[i]);
}
int cnt=inf;
for(int i=;i<s;i++)
{
dijstra(start[i]);///对每个起点使用
for(int j=;j<d;j++)///求到多个目的地的距离中的最小
{
cnt=cnt>dis[end1[j]]?dis[end1[j]]:cnt;
}
} printf("%d\n",cnt);
}
return ;
}

网搜其他解法,抽时间理解学习,加注释。

法二:SPFA, 将起点都推入队列。求出各个终点的最短时间。然后再找到最短的;

///SPFA shortest path faster algorithm
#include <cstdio>
#include <vector>
#include <algorithm>
#include <queue>
#define INF 0xfffffff
const int maxn = ;
using namespace std;
struct node{
int v,len;
node(int v=,int len=):v(v),len(len){}
};
int st[];
int goal[];
vector<node>G[maxn];
int minDist[maxn];
int inqueue[maxn];
int n,m;
int T,S,D;
void init(){
for(int i=;i<maxn;i++){
minDist[i]=INF;
inqueue[i]=;
G[i].clear();
}
}
int Dijkstra(){
queue<int >Q;
for(int i=;i<S;i++){ ///将所有的起点 都推入队列
inqueue[st[i]]=true;
minDist[st[i]]=;
Q.push(st[i]);
}
while(!Q.empty()){
int vex = Q.front();
Q.pop();
inqueue[vex]=;
for(int i=;i<G[vex].size();i++){
int v = G[vex][i].v;
if(G[vex][i].len+minDist[vex]<minDist[v]){ ///松弛操作,找到最短边
minDist[v]=G[vex][i].len+minDist[vex];
if(!inqueue[v])
{
inqueue[v]=;
Q.push(v);
}
} }
}
int Min = INF;
for(int i=;i<D;i++){ ///在终点找到用时最小的终点
Min = min(minDist[goal[i]],Min);
}
printf("%d\n",Min);
}
int main(){ while(scanf("%d%d%d",&T,&S,&D)!=EOF){
init();
int a,b,len;
for(int i=;i<T;i++){
scanf("%d%d%d",&a,&b,&len);
G[a].push_back(node(b,len));
G[b].push_back(node(a,len));
}
for(int i=;i<S;i++){
scanf("%d",&st[i]);
}
for(int i=;i<D;i++){
scanf("%d",&goal[i]);
}
Dijkstra();
}
return ;
}
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
int t, s, d, k;
int dis[];
bool vis[];
int goal[];
struct edge
{
int v, w, next;
}e[];
int head[];
queue <int> q;
void adde(int u, int v, int w)
{
e[k].v = v;
e[k].w = w;
e[k].next = head[u];
head[u] = k++;
}
void input()
{
int u, v, w;
for (int i = ; i <= t; i++)
{
scanf("%d%d%d", &u, &v, &w);
adde(u, v, w);
adde(v, u, w);
}
for (int i = ; i < s; i++)
{
scanf("%d", &v);
adde(, v, );
adde(v, , );
}
for (int i = ; i < d; i++)
scanf("%d", &goal[i]);
}
void init()
{
k = ;
memset(head, -, sizeof(head));
memset(dis, 0x3f, sizeof(dis));
memset(vis, , sizeof(vis));
dis[] = ;
while (!q.empty())
q.pop();
}
void spfa()
{
q.push();
vis[] = ;
while (!q.empty())
{
int u = q.front();
q.pop();
vis[u] = ;
for (int i = head[u]; i != -; i = e[i].next)
{
int v = e[i].v;
if (dis[v] > dis[u] + e[i].w)
{
dis[v] = dis[u] + e[i].w;
if (!vis[v])
{
vis[v] = ;
q.push(v);
}
}
}
}
}
void solve()
{
int ans = 0x3f3f3f3f;
spfa();
for (int i = ; i < d; i++)
ans = min(ans, dis[goal[i]]);
printf("%d\n", ans);
}
int main()
{
while (scanf("%d%d%d", &t, &s, &d) == )
{
init();
input();
solve();
}
return ;
}

法三:

【Floyd-Warshall算法】

效率是O(n^3) 用到了DP的思想

#include <cstdio>
#include <vector>
#include <queue>
#define INF 0xfffff
const int maxn = ;
using namespace std;
int map[maxn][maxn];
int st[maxn];
int goal[maxn];
void init(){
for(int i=;i<maxn;i++){
for(int j=;j<maxn;j++){
if(i==j) map[i][j]=;
else
map[i][j]=INF;
}
}
}
int main(){
int T,S,D;
while(scanf("%d%d%d",&T,&S,&D)!=EOF){
init();
int a,b,len;
int Min=INF,Max=-;
for(int i=;i<T;i++){
scanf("%d%d%d",&a,&b,&len);
if(a>Max) Max = a;
if(b>Max) Max = b;
if(b<Min) Min = b;
if(a<Min) Min =a;
if(len<map[a][b])
{
map[a][b]=map[b][a]=len;
}
}
for(int k=Min;k<=Max;k++){
for(int i=Min;i<=Max;i++){
if(map[i][k]!=INF) ///没有这句优化就超时了
for(int j=Min;j<=Max;j++){
if(map[i][j]>map[i][k]+map[k][j])
map[i][j]=map[i][k]+map[k][j];
}
}
}
for(int i=;i<S;i++)
scanf("%d",&st[i]);
for(int i=;i<D;i++)
scanf("%d",&goal[i]);
int ans=INF;
for(int i=;i<S;i++){
for(int j=;j<D;j++){
if(map[st[i]][goal[j]]<ans)
ans=map[st[i]][goal[j]];
}
}
printf("%d/n",ans);
}
return ;
}

HDU2066一个人的旅行---(多起点多终点最短路径)的更多相关文章

  1. dump 验证实例恢复的起点和终点

    什么时候会产生实例恢复呢?当你数据库服务器异常断电,重启数据库就会发生实例恢复.实例恢复是由数据库自动完成的,无须DBA的干涉.当然这里有个前提条件:数据文件. 在线日志文件.控制文件不得有损坏. 我 ...

  2. 【百度地图API】让用户选择起点和终点的驾车导航

    原文:[百度地图API]让用户选择起点和终点的驾车导航 摘要: 如果用户搜索“从机场到火车站”,使用驾车导航DrivingRoute会默认显示一条结果.但同一个城市可能有多个机场和火车站,那么,如何用 ...

  3. Coolest Ski Route-不定起点和终点----在有向变的情况下---求最长路

    这题最开始给你了N个点,M条边,边是单向边,问不指定起点和终点,最长路是什么??? 脑补一下,不定起点和终点的最短路,用弗洛伊德算法搞一搞,但是...那个垃圾算法的复杂度是N^3的,但是这个算法的M高 ...

  4. hdu 2066 多起点 多终点

    多起点 多终点 无向图 结点的个数要自己求 Sample Input6 2 3 //边数 起点数 终点数1 3 5 //u v w1 4 72 8 123 8 44 9 129 10 21 2 //起 ...

  5. 【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】

    Solution 注意取模!!! Code #include<bits/stdc++.h> #define mod 1000000007 #define LL long long usin ...

  6. Key Vertex (hdu 3313 SPFA+DFS 求起点到终点路径上的割点)

    Key Vertex Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Tota ...

  7. 【10.3校内测试【国庆七天乐!】】【DP+组合数学/容斥】【spfa多起点多终点+二进制分类】

    最开始想的暴力DP是把天数作为一个维度所以怎么都没有办法优化,矩阵快速幂也是$O(n^3)$会爆炸. 但是没有想到另一个转移方程:定义$f[i][j]$表示每天都有值的$i$天,共消费出总值$j$的方 ...

  8. HDU——2612Find a way(多起点多终点BFS)

    Find a way Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  9. hdu2066一个人的旅行(dijkstra)

    Problem Description 虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰 ...

随机推荐

  1. HashMap源码注释翻译

    HashMap.java(JDK1.8) 如有错误翻译的地方,欢迎评论指出. 介绍:对于HashMap及其子类而言,它们采用Hash算法来决定集合中元素的存储位置.当系统开始初始化HashMap时,系 ...

  2. axios应用

    Skip to content     Features Business Explore Marketplace Pricing Sign in or Sign up     Watch929 St ...

  3. OrCAD创建原理图符号图

    1. 首先创建一个库 2. 右键新创建的库,添加新的器件New Part 3. 修改器件属性 4. 添加引脚 添加完引脚之后如图,其中双击引脚,即可修改引脚名字和序号 5. 添加符号的外形 添加完外形 ...

  4. redis入门:介绍、特点、安装、各类型常用操作

    一.redis介绍 Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. Redis支持多种类型的数据结构,如 字符串(strings), 散列(ha ...

  5. Python 3基础教程20-Python中导入模块和包

    本文介绍Python中导入模块和包 #目录: # 导入模块和包--- # | # 上级包.上级模块.导入模块和包的init模块----- # | # 同级包.同级模块.上级包的init模块.test模 ...

  6. 3、shader深度测试(Cull、ZWrite 、ZTest )

    剔除和深度测试是渲染法线中的一个流程 Cull:默认情况下,Unity中给的所有Shader都是单面的,它都把反面的渲染给关闭掉了,如果你在开发的过程中需要使用到双面,只要把cull关闭(off)即可 ...

  7. [Effective Java] 创建和销毁对象篇

    [Effective Java] 创建和销毁对象篇 1. 优先考虑用静态工厂方法代替构造器 优点: - 静态工厂方法相比于构造器,它们有名称 - 不需要每次在使用的时候创建一个对象 - 可以返回原返回 ...

  8. SpringBoot:工厂模式实现定时任务可配置

    pringBoot:工厂模式实现定时任务可配置 需要:使用springboot,实现定时任务可配置. 定时任务可在代码中写死,在配置文件中配置,这些都不能实现定时任务在服务器不重启的情况下可配置. 为 ...

  9. HDU 3696 Farm Game(拓扑+DP)(2010 Asia Fuzhou Regional Contest)

    Description “Farm Game” is one of the most popular games in online community. In the community each ...

  10. lintcode-117-跳跃游戏 II

    117-跳跃游戏 II 给出一个非负整数数组,你最初定位在数组的第一个位置. 数组中的每个元素代表你在那个位置可以跳跃的最大长度. 你的目标是使用最少的跳跃次数到达数组的最后一个位置. 样例 给出数组 ...