hrbust 1339 Touring【最短路+思维】

Touring

Time Limit: 1000 MS

Memory Limit: 32767 K

 

Total Submit: 294(57 users)

Total Accepted: 126(49 users)

Rating: 

Special Judge: No

 

Description

The best friends Mr. Li and Mr. Liu are touring in beautiful country M.

M has n cities and m two-way roads in total. Each road connects two cities with fixed length.We assume that the cost of car traveling on the road is only related to the length of road,the longer road the more money to pay. 

Now,both Mr. Li and Mr. Liu are in the city C,they have chosen to travel separately by the next time.

Mr. Li chooses city A with beautiful scenery to be next place, Mr. Liu goes to city B with ancient temples.

You are their friend with clever minds,just tell them how to arrive the target places make total costs of them minimum.

Input

The input file contains sevearl test cases.The first line of each case are two positive integers n,and m(3<=n<=5000, 1<=m<=10000). The cities are named from 1 to n.Three positive integers C, A, B are follwing.Then,m lines are given,each line contains three integers i,j and k,indicating one road between i and j is exists,and should pay cost k by the car.

 

Process to the end of file.

Output

For each test case, first print a line saying "Scenario #p", where p is the number of the test case.Then,if both Mr. Li and Mr. Liu can manage to arrive their cities,output the minimum cost they will spend,otherwise output "Can not reah!", in one line.Print a blank line after each test case, even after the last one.

Sample Input

4 5

1 3 4

1 2 100

1 3 200

1 4 300

2 3 50

2 4 100

4 6

1 3 4

1 2 100

1 3 200

1 4 300

2 3 50

2 4 100

3 4 50

Sample Output

Scenario #1

250

Scenario #2

200

Hint

The car can carry with both of them at the same time.

For case 1:Li and Liu can take car together from 1 to 2, and then Li can take car from 2 to 3,Liu can take car from 2 to 4,so the total cost is 100+50+100.

 

题目大意:

有n个城市,m条无向边,源点为C,在源点有两个人,一个人想去A城市,一个人想去B城市,两人可以一起出发,重叠的路线算作一次消耗,求一个最优方案的消耗和。


思路:


1、刚开始的时候,想要求一遍从源点C的最短路然后记录路径,然后在path【a】和path【b】中去掉重叠路线,但是这样的思路是错误的。明显从一个点出发不直接到终点a或者终点b的另外一个点z,再从z到a和b也是可能比从c直接到a和b的最短距离小的。


2、所以正确的思路就是枚举从源点C到点i( 1<=i<=n)的路径,然后再加上从点i到点b和点c的距离,这个和枚举出来之后维护最小值即可。


3、枚举从源点c到i的路径,求一次以c为源点的最短路。从点i到点 b的距离,我们可以求一次以b为源点的最短路,因为是无向图,不需要反向建边去求,从b到i的最短路,就是从i到b的最短路,同理,再求一次以c为源点的最短路。


4、即ans=min(dis【0】【i】+dis【1】【i】+dis【2】【i】)【1<=i<=n】


5、因为求三遍最短路,而且n的值和m的值都比较大,我们使用SPFA求最短路。


6、注意这个题虽然没有给出边权值的范围,但是很坑,三者加和的值会爆long long 所以这里需要注意一下,而且格式输出也要注意一下。


AC代码:

#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
int head[100000];
struct EdgeNode
{
    int to;
    int w;
    int next;
}e[100000];
int vis[100000];
long long int dis[3][100000];
int n,m,cont;
int s,t1,t2;
void add(int from,int to,int w)
{
    e[cont].to=to;
    e[cont].w=w;
    e[cont].next=head[from];
    head[from]=cont++;
}
void SPFA(int ss,int z)
{
    for(int i=1;i<=n;i++)
    {
        dis[z][i]=0x3f3f3f3f;
    }
    dis[z][ss]=0;
    vis[ss]=1;
    queue<int >s;
    s.push(ss);
    while(!s.empty())
    {
        int u=s.front();
        s.pop();vis[u]=0;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            int w=e[i].w;
            if(dis[z][v]>dis[z][u]+w)
            {
                dis[z][v]=dis[z][u]+w;
                if(vis[v]==0)
                {
                    vis[v]=1;
                    s.push(v);
                }
            }
        }
    }
}
int main()
{
    int kase=0;
    while(~scanf("%d%d",&n,&m))
    {
        cont=0;
        memset(head,-1,sizeof(head));
        scanf("%d%d%d",&s,&t1,&t2);
        for(int i=0;i<m;i++)
        {
            int x,y,w;
            scanf("%d%d%d",&x,&y,&w);
            add(x,y,w);
            add(y,x,w);
        }
        SPFA(s,0);
        SPFA(t1,1);
        SPFA(t2,2);
        long long int output=9999999999999999;
        for(int j=1;j<=n;j++)
        {
            output=min(output,dis[0][j]+dis[1][j]+dis[2][j]);
        }
        printf("Scenario #%d\n",++kase);
        if(output>=9999999999999999)
        printf("Can not reah!\n\n");
        else
        printf("%lld\n\n",output);
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值