迪杰斯特拉板子

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <vector>
  6 #include <stack>
  7 using namespace std;
  8 const int maxn=505;
  9 const int INF=0x3f3f3f3f;
 10 int n,m,s,d;
 11 int sp[maxn]; //救援人数
 12 int dj[maxn]; //距离起点最短距离
 13 int vis[maxn];//是否列入集合
 14 int road[maxn];//最短路径条数
 15 int path[maxn];//前缀节点
 16 int total[maxn];//总救援人数
 17 struct city
 18 {
 19     int e;
 20     int len;
 21 };
 22 vector <city> ve[maxn];
 23 //初始化
 24 void init ()
 25 {
 26     memset (vis,0,sizeof(vis));
 27     memset (total,0,sizeof(total));
 28     memset (road,0,sizeof(road)); 
 29     memset (path,-1,sizeof(path));
 30     for (int i=0;i<n;i++)
 31         dj[i]=INF;
 32     dj[s]=0;
 33     total[s]=sp[s];
 34     road[s]=1;
 35 }
 36 void djst ()
 37 {
 38     while (1)
 39     {
 40        int maxx=INF;
 41        int u=-1;
 42        for (int i=0;i<n;i++)
 43             if(dj[i]<maxx&&!vis[i])
 44             {
 45                maxx=dj[i];
 46                u=i;
 47             }
 48        if(u==-1)//如果u依旧还是等于-1说明全部点都已经最小了,循环结束 
 49           break;
 50        vis[u]=1;//不然以u点作为中介来向周围扩展 
 51        for (int i=0;i<ve[u].size();i++)
 52        {
 53            int v=ve[u][i].e;//以u点通过u点的边能找到v点,从而扩散v点 
 54            if(!vis[v])//如果v点还没访问过 
 55            {
 56                if(dj[v]>dj[u]+ve[u][i].len)//如果直接到v点比通过u到达v更远,则更新一下 
 57                {
 58                   dj[v]=dj[u]+ve[u][i].len;
 59                   path[v]=u;//记录一下路径,到v的前驱是u 
 60                   road[v]=road[u];//到v的最短路径与到u的最短路径条数一样 
 61                   total[v]=total[u]+sp[v];//到v的救援人数是到u的人数+v的救援人数 
 62  
 63                }
 64                else if(dj[v]==dj[u]+ve[u][i].len)//如果直接到V和通过u到v的长度一样 
 65                {
 66                    //这里要写到if语句外面
 67                     road[v]+=road[u];//那到v的最短路径数就要加上到u的最短路径条数 
 68                     if(total[u]+sp[v]>total[v])//更新救援人数和路径,因为题目中救援人数是第二关键字 
 69                     {
 70                        path[v]=u;//如果可以更新,那么v的前驱就必须是u 
 71                        total[v]=total[u]+sp[v];
 72                     }
 73                }
 74            }
 75        }
 76     }
 77 }
 78 //输出函数
 79 void output()
 80 {
 81     printf("%d %d\n",road[d],total[d]);
 82     int temp=d;
 83     stack<int>ss;
 84     while (path[temp]!=-1)
 85     {
 86         ss.push(temp);
 87         temp=path[temp];
 88     }
 89     ss.push(s);
 90     while (!ss.empty())
 91     {
 92         printf("%d%c",ss.top(),ss.size()==1? '\n':' ');
 93         ss.pop();
 94     }
 95 }
 96 int main()
 97 {
 98     scanf("%d%d%d%d",&n,&m,&s,&d);
 99     for (int i=0;i<n;i++)
100         scanf("%d",&sp[i]);
101     init();
102     for (int i=0;i<m;i++)
103     {
104         int x,y,len;
105         scanf("%d%d%d",&x,&y,&len);
106         city temp1,temp2;
107         temp1.e=y; temp1.len=len;
108         temp2.e=x; temp2.len=len;
109         ve[x].push_back(temp1);//无向图 
110         ve[y].push_back(temp2);
111     }
112     djst();
113     output();
114     return 0;
115 }

猜你喜欢

转载自www.cnblogs.com/ShadowCharle/p/11737586.html