HDU 2680 Choose the best route 最短路(Dijkstra算法)

Choose the best route

                                                                       Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


Problem Description
One day , Kiki wants to visit one of her friends. As she is liable to carsickness , she wants to arrive at her friend’s home as soon as possible . Now give you a map of the city’s traffic route, and the stations which are near Kiki’s home so that she can take. You may suppose Kiki can change the bus at any station. Please find out the least time Kiki needs to spend. To make it easy, if the city have n bus stations ,the stations will been expressed as an integer 1,2,3…n.
 

Input
There are several test cases. 
Each case begins with three integers n, m and s,(n<1000,m<20000,1=<s<=n) n stands for the number of bus stations in this city and m stands for the number of directed ways between bus stations .(Maybe there are several ways between two bus stations .) s stands for the bus station that near Kiki’s friend’s home.
Then follow m lines ,each line contains three integers p , q , t (0<t<=1000). means from station p to station q there is a way and it will costs t minutes .
Then a line with an integer w(0<w<n), means the number of stations Kiki can take at the beginning. Then follows w integers stands for these stations.
 

Output
The output contains one line for each data set : the least time Kiki needs to spend ,if it’s impossible to find such a route ,just output “-1”.
 

Sample Input
  
  
5 8 5 1 2 2 1 5 3 1 3 4 2 4 7 2 5 6 2 3 5 3 5 1 4 5 1 2 2 3 4 3 4 1 2 3 1 3 4 2 3 2 1 1
 

Sample Output
  
  
1 -1

 

最短路的模板题目,但是唯一的不同的是多个起点,而且图是有向图,不是无向图,所以要注意输入。有两种思路

思路一:在建立一个节点作为这些起点的起点,注意是两者之间的距离是0;

思路二:把起点和终点调换一下,起点作为终点,终点是起点,然后最短路,输入的时候也要注意颠倒顺序。


思路一代码

#include<stdio.h>
#include<iostream> 
#include <algorithm>
#include<string.h>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
int KGCD(int a,int b){if(a==0)return b;if(b==0)return a;if(~a&1){ if(b&1) return KGCD(a>>1,b);else return KGCD(a>>1,b>>1) <<1; } if(~b & 1)  return KGCD(a, b>>1);  if(a > b) return KGCD((a-b)>>1, b);return KGCD((b-a)>>1, a);}  
int LCM(int a,int b){ return a/KGCD(a,b)*b; } 
int dir[5][2]={0,1,0,-1,1,0,-1,0};
using namespace std;
int n,m;
int map[1005][1005];//地图 
int map1[1005];//单元最短路 
int vis[1005];//记录访问 
void dijkstra()
{
	int k;
	memset(vis,0,sizeof(vis));
	vis[0]=1;//起点标记下
	for(int i=0;i<n;i++)//每个点作为起点搜索一边所有的最短路 
	{
		int min=INF;
		k=1;
		for(int j=0;j<=n;j++)
		{
			if(!vis[j] && min > map1[j])
			{
				min=map1[j];
				k=j;
			}
		}
		vis[k]=1;
		for(int j=0;j<=n;j++)
		{
			if(!vis[j] && map1[j] > map1[k] + map[k][j])
				map1[j]=map1[k]+map[k][j];
		}
	} 
}
int main()
{
	int x,y,z,t;
	while(scanf("%d%d%d",&n,&m,&t)!=EOF)
	{
		for(int i=0;i<=n;i++)//先整理出来地图 
		{
			for(int j=0;j<=n;j++)
			    map[i][j]=INF;
		}
		for(int i=0;i<m;i++)
		{
			scanf("%d%d%d",&x,&y,&z);
			if(z<map[x][y])		//避免重遍  只要最小的 
				map[x][y]=z;
		}
		scanf("%d",&y);
		for(int i=0;i<y;i++)
		{
			scanf("%d",&x);
			map[0][x]=0;
		}
		for(int i=0;i<=n;i++)
		{
			map1[i]=map[0][i];
		}
		dijkstra();
		if(map1[t]==INF)
			printf("-1\n");
		else
			printf("%d\n",map1[t]);
	}
	return 0;	
} 

思路二:(贴的别人的代码)


#include<stdio.h>
#include<string.h>
#define INF 1<<26
const int N = 1e3 + 10;
int w[N][N], d[N];

void Dijkstra(int n, int u)
{
    int vis[N], i;
    memset(vis, 0, sizeof(vis));
    for(i = 1; i <= n; i++)
        d[i] = INF;
    d[u] = 0;
    for(i = 1; i <= n; i++)
    {
        int x = u, temp = INF;
        for(int y = 1; y <= n; y++)
            if(!vis[y] && d[y] < temp)
                temp = d[x = y];
        if(temp == INF) break;
        vis[x] = 1;
        for(int y = 1; y <= n; y++)
            if(d[y] > d[x] + w[x][y])
                d[y] = d[x] + w[x][y];
    }
}

int main()
{
    int n, m, des, i, j;
    while(~scanf("%d%d%d",&n, &m, &des))
    {
        for(i = 1; i <= n; i++)
            for(j = 1; j <= n; j++)
            {
                if(i == j)
                    w[i][j] = 0;
                else
                    w[i][j] = INF;
            }
        int a, b, c;
        for(i = 0; i < m; i++)
        {
            scanf("%d%d%d",&a, &b,&c);
            if(c < w[b][a])
                w[b][a] = c;
            //路也反向
        }
        Dijkstra(n, des); //终点作为起点
        int num, Min_path = INF, p;
        scanf("%d",&num);
        for(i = 0; i < num; i++)
        {
            scanf("%d",&p);
            if(d[p] < Min_path)
                Min_path = d[p]; //记录最小值
        }
        if(Min_path < INF)
            printf("%d\n",Min_path);
        else
            printf("-1\n");
    }
    return 0;
}
思路其实是一样的,只不过第二个是先求出来最短路,然后再去求起点和终点之间的距离是否满足要求,画一下图就出来了~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值