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

迪杰斯特拉问题:郁闷了好久终于有头绪了,这问题还纠结,但是终于解决了。。就是要注意几个问题:首先对于问题必须分清楚初始位置与末位置,只是在DIJ问题中最重要的的,其次就是要把握好是:题目给的是路径数目还是有多少地点,而且对于地点数多数是以数据来明地点的,因此在只给出对少条路径时,也就必须比较出最大的地点是多少,就如此题,题目不是给的地点数,而是路径数。在写的时候就得注意。。。

还有特别注意是就是:对于一般的DIJ问题都是直接给出地点数目,路径长度,还有直接求出已定的初始位置到末位置的最短距离。。但是有的就不一定全给出来的,而是要自己求出来,如此题》而且此题并没有直接给出初始位置和末位置,而要我们求最短路径所花的时间最短(在已给出的莫位置比较最小的,切记不是在所有地点中最短的)。。

因此这就考虑用到虚点的引用,就是在没有的点,而设出它点,因此达到所需的效果,这里初始位置其实是已经给出的,但是还是的注意下,因为题目说草儿的点到1,2,为相邻,这就说草儿到1,2 的时间就是0,因此虽没说明但是还是可以以草儿的地点为初始点(为s),这就是第一个虚点,其实还可以设一个虚点,我个人觉得容易理解,就是在最后的位置设一个虚点作为终点(E),就是把题目所给的几个终点到这个虚点为相邻,因此就是虚点到几个给定的终点的时间为0。

这样就可以真正意义上利用DIJ了,初始位置为(S),末位置为(E),直接DIJ,贴代码:

见代码:

#include<iostream>//设两个虚点,就确定是从虚点0到虚点t+1的距离,直接就是利用迪杰斯特拉算法。。但是一直交不了,(WA好多次了)哎。。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
# define MAX 100010
# define LMN 1005
int dis[LMN][LMN],loc[LMN];
bool flag[LMN];
void init()                                //初始化。
{
    int i,j;
    for(i=0;i<LMN;i++)
    {
        for(j=0;j<LMN;j++)
        {
            if(i==j)
            {
                dis[i][j]=0;
            }
            else
                dis[i][j]=MAX;
        }
    }
}
void dijstra(int n,int s)              //dij   n 为地点的个数,s为初始点。
    int i,j,min,k;
    memset(flag,false,sizeof(flag));
    for(i=0;i<=n;i++)
    {
        loc[i]=dis[s][i];
    }
    loc[s]=0;
    flag[s]=true;
    for(j=1;j<=n;j++)
    {
        min=MAX;
        for(i=0;i<=n;i++)
        {
            if(!flag[i]&&min>loc[i])
            {
                min=loc[i];
                k=i;
            }
        }
        //if(min==MAX)
       //     break;
        flag[k]=true;
        for(i=0;i<=n;i++)
        {
            if(!flag[i]&&loc[i]>loc[k]+dis[k][i])
            {
              loc[i]=loc[k]+dis[k][i];
            }
        }
    }
}
int  main()
{
    int i,j,n,s,d;
    while(scanf("%d%d%d",&n,&s,&d)!=EOF)
    {
        int a,b,m,t=-9999;
        init();
        for(i=1;i<=n;i++)
        {
            scanf("%d%d%d",&a,&b,&m);
            if(t<max(a,b))           //找出做大的数,作为最大的地点,为地点个数,注意用的时候要注意,必须加1.因为设了一个末位置的虚点。。如不加1,就不会运行到末位置(虚点)。
            {
                t=max(a,b);
            }
            if(dis[a][b]>m)     //这里尤其注意。当初我就是这里三行没写而一直错这里些写是为了避免中间出现相邻的情况。
            {
                 dis[a][b]=dis[b][a]=m;
            }
        }
        int x,y;
        for(i=1;i<=s;i++)           //初始点的虚点设置。。
        {
            scanf("%d",&x);
            dis[0][x]=dis[x][0]=0;    //注意设为0,相邻,
        }
        for(i=1;i<=d;i++)     //终点的虚点设置,
        {
            scanf("%d",&y);
            dis[y][t+1]=dis[y][t+1]=0;  //值一样设为0.
        }
        dijstra(t+1,0);
        printf("%d\n",loc[t+1]);
    }
    return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值