【最短路】逃离遗迹 escape.pas/c/cpp

逃离遗迹

Problem:       escape.pas/c/cpp
Input:       escape.in
Output:       escape.out
Memory Limit:   128 MB
Time Limit:      1 sec

  【题目描述】

根据外星人的回信,在遗迹分布着三样道具。当三样道具都拿走后,遗迹就很快自动毁灭,所以必须要在最短时间内离开。遗迹可以看作是由N个房间(编号1..N)和N-l条长度不等通道所组成,并且任意两个房间之间有且只有一条路可以相互到达。现在我们的队员已经在编号为A,B,C的房间内拿到道具,并且准备撤退。由于只有一架直升机,所以只能在一个房间上停留。现在请你决定将直升机停在哪一个房间之上,能够使三人到达该房间的距离之和最短。

  【输入格式】

  第1行:四个整数N、A、B、C。

  第2..N行:每行三个整数u,v,w,表示存在连接房间u,v的通道,长度w。

  【输出格式】

  第1行:一个整数,表示汇合房间的编号。若存在多个解,输出序号最小的。

  第2行:一个整数,表示三人到该房间距离之和。

  【输入样例】

5 3 1 4

3 5 5

4 3 9

4 1 7

1 2 1

【输出样例】

4

16

【数据范围】

  对于50%的数据:1≤N≤1,000。  对于l00%的数据:1≤N≤20,000。

  1≤A,B,C,u,v<=N且A,B,C不相等;u,v不相等。  1≤w≤1,000。

 

 

 

这一题很容易想到用三次spfa,求出所有点分别到a,b,c的最短距离,最后枚举找最优即可(上午想错了,以为只能是ABC三点任意一点,结果任何点都可以。。。)

当然利用数据的特殊性,是一棵树,每两点只有一条路,那么就可以宽搜,第一次找到目标点就肯定是最短的,最后枚举找最优

 

C++ Code

/*
C++ Code
http://oijzh.cnblogs.com
By jiangzh
*/
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define MAXN 20010

int n,A,B,C;
struct link{int y,z;link *next;};
link *head[MAXN];
int dist[5][MAXN];//dist[x][]表示 x 到任意点的最短距离(或者说任意点到 x 的最短距离)
queue<int> q;

void insert(int x,int y,int z)
{
    link *node = new link;
    node->y=y;node->z=z;
    node->next=head[x];
    head[x]=node;
}

void init()
{
    freopen("escape.in","r",stdin);
    freopen("escape.out","w",stdout);
    
    scanf("%d%d%d%d",&n,&A,&B,&C);
    int x,y,z;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        insert(x,y,z);
        insert(y,x,z);
    }
}

void spfa(int xxx,int std)
{
    dist[xxx][std]=0;q.push(std);
    while(!q.empty())
    {
        int x=q.front();q.pop();
        link *node=head[x];
        while(node)
        {
            int y=node->y,z=node->z;
            if(dist[xxx][y]>dist[xxx][x]+z)
            {
                dist[xxx][y]=dist[xxx][x]+z;
                q.push(y);
            }
            node=node->next;
        }
    }
}

void work()
{
    memset(dist,0x07,sizeof(dist));
    spfa(1,A);
    spfa(2,B);
    spfa(3,C);
    int ans=0x07070707,k=0;
    for(int i=1;i<=n;i++)
        if(ans>dist[1][i]+dist[2][i]+dist[3][i])
        {
            ans=dist[1][i]+dist[2][i]+dist[3][i];
            k=i;
        }

    if(ans==0x07070707) printf("-1");
    else printf("%d\n%d",k,ans);
}

int main()
{
    init();
    work();
    return 0;
}

  

 

posted @ 2012-11-06 13:33  jiangzh  阅读(654)  评论(0编辑  收藏  举报