hdu2680(最短路spfa!此题有重大发现)

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

         题意是先输入三个数,分别表示总共公交站台个数n,公交车路线个数m,目的地的公交站台s,然后输入m个公交线路,一对边和权值,然后输入一个数w表示最初能去的公交站台的个数,接下来w个数分别是最初可以到达的公交站台;求到达目的地s的最短时间(最小权值)。题目一看就知道是最短路,不过显然这题与别的题目有点不一样的是初始站台很多个,目标站台只有一个,这种情况对于像我这种只会spfa的弱鸡可怎么办好,如果把所有的初始站台都来一遍spfa那最坏情况999次,在乘以每一次的spfa时间复杂度那真是够我受的了,于是,机智的弱鸡想到了一个好办法,这题不就是求很多源点到一个点的最短路径吗,我们如果把题目给我们的初始边反转,反过来不就是求目标点到所有源点的最短路径吗?所以这样子就直接把问题化简为了只调用一次spfa,正在弱鸡兴奋之余,一股脑敲完代码就提交了,于是一股脑的脑残TLE了,弱鸡想想,哎哟,不对哟!怎么可能?!!我可是把最坏情况都优化到了调用spfa一次呢!!!为啥还是TLE呢5555~~~

        于是,弱鸡因此发现了一个重大发现!弱鸡去网上看了看别人用spfa过的代码,看看之后觉得,嗯?难道是杭电oj故意***难我?于是一股脑在交了3次。于是。。。结果大家懂的。

        唉,弱鸡只好细心比对代码,一个个比对一个个比对呀!发现只不过人家写的队列而弱鸡用的栈(还是写的模拟),由于还不会直接用STL的队列和栈,于是弱弱的我只好把模拟栈改成的模拟对列,结果大出我所料!!!!!!弱鸡简直是兴奋极了!!!!一个顺序的不同却直接造成了时间的巨大差异。这足以说明spfa还是具有偶然性,(并不能说明只能用队列写,有的情况是只能用栈不能用队列!)

所以以后写spfa的时候弱鸡会注意这些的,同时还得去读读上次某学长给的人品导论,要是比赛遇到了只求人品好一遍ac!

#include <iostream>
#include <cstdio>
#include <cstring>
#include<algorithm>
#define max0 999999
using namespace std;

int dl[1000000],cc[1005][1005],dis[1005];
bool vis[1005];

int min0(int a,int b)
{
    return a>b?b:a;
}

void spfa(int s,int n)
{
    int r=0,l=0;
    memset(dl,0,sizeof(dl));
    memset(vis,1,sizeof(vis));
    for(int i=1;i<=n;i++)
        dis[i]=max0;
    dis[s]=0;
    dl[r++]=s;
    while(l<r)
    {
        int x=dl[l];
        vis[x]=1;
        for(int i=1;i<=n;i++)
        {
            if(cc[x][i]!=max0)
            {
                if(dis[i]>dis[x]+cc[x][i])
            {
                dis[i]=dis[x]+cc[x][i];
                if(vis[i])
                {
                    dl[r++]=i;
                    vis[i]=0;
                }
            }
            }
        }
        l++;
    }
}

int main()
{
    int n,m,s;
    while(~scanf("%d%d%d",&n,&m,&s))
    {
        int a,b,c;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            if(i!=j)cc[i][j]= max0;else cc[i][j]=0;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(c<cc[b][a])
            cc[b][a]=c;
        }
        spfa(s,n);
        int q,sum=max0;scanf("%d",&q);
        while(q--)
        {
            int p;scanf("%d",&p);
            sum=min0(sum,dis[p]);
        }
        if(sum==max0)printf("-1\n");
        else printf("%d\n",sum);
    }
    return 0;
}

posted @ 2015-10-15 18:36  martinue  阅读(275)  评论(0编辑  收藏  举报