模板-PA1030二标尺最优路径并打印路径

2019-03-16  本文已影响0人  余生筑
/*Dijkstra+DFS解法

Dijkstra(st)
DFS(ed)
sum(st)
print(st)*/
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXV=510;
const int INF=100000000;//INF不要用INT_Max,C++有时会判断INT_Max小于0
int minCost=INF;
int n,m,st,ed,G[MAXV][MAXV];//顶点数,边数,起点,终点
int cost[MAXV][MAXV];
int d[MAXV];//d[ed]=x表示从起点到终点的最短距离为x
int num[MAXV];//最短路径数目
bool vis[MAXV]= {false}; //vis[ed]=true表示顶点ed已入树
int k=0;
vector<int> pre[MAXV];//pre[ed]={v1,v2,v3}表示从起点到终点的最短路径有3条,且前驱顶点分别为v1,v2,v3;
int tempPath[MAXV],path[MAXV];

void Dijkstra(int s)//s为起点
{
    fill(d,d+MAXV,INF);
    d[s]=0;
    for(int i=0; i<n; i++)
    {
        int u=-1,MIN=INF;
        for(int j=0; j<n; j++)
        {
            if(vis[j]==false&&d[j]<MIN)
            {
                u=j;
                MIN=d[j];
            }
        }
        if(u==-1)//找不到小于INF的d[u],说明剩下的顶点和起点s不连通
            return;
        vis[u]=true;

        //遍历,判断v能否作为中介点
        for(int v=0; v<n; v++)
        {
            if(vis[v]==false&&G[u][v]!=INF)
            {
                if(d[u]+G[u][v]<d[v])
                {
                    d[v]=d[u]+G[u][v];
                    pre[v].clear();//令v的前驱为u
                    pre[v].push_back(u);
                }
                else if(d[u]+G[u][v]==d[v])
                    pre[v].push_back(u);
            }
        }
    }
}

//求边权和
int sum(int v)
{
    int a=0;
    while(v!=ed)
    {
        a+=cost[v][tempPath[v]];
        v=tempPath[v];
    }
    return a;
}

//打印路径(从起点到终点)
void print(int v)
{
    printf("%d",v);
    while(v!=ed)
    {
        printf(" %d",path[v]);
        v=path[v];
    }
}

void DFS(int v)
{
    if(v==st)
    {
        //num++;如果需要统计由Dijkstra算法生成的最短路径数目,就需要这句
        int costSum=sum(v);
        if(costSum<minCost)//假如"当前路径权值和"小于"当前最小路径权值和",则刷新"当前最小路径权值和"
        {
            minCost=costSum;
            memcpy(path,tempPath,sizeof(tempPath));
        }
        return;
    }

    for(int i=0; i<pre[v].size(); i++)//在该题中,pre[3]={1,2};pre[2]={0};pre[1]={0};
    {
        tempPath[pre[v][i]]=v;//比如起点至终点为的一条最短路径为0-1-3,则tempPath[1]=3;tempPath[0]=1;
        DFS(pre[v][i]);
    }
}

int main()
{
    cin>>n>>m>>st>>ed;
    int u,v,l,co;
    fill(G[0],G[0]+MAXV*MAXV,INF);
    fill(cost[0],cost[0]+MAXV*MAXV,INF);
    for(int i=0; i<m; i++)
    {
        cin>>u>>v>>l>>co;
        G[u][v]=G[v][u]=l;
        cost[u][v]=cost[v][u]=co;
    }
    Dijkstra(st);
    DFS(ed);

    print(st);
    printf(" %d %d\n",d[ed],minCost);
}
/*
输入:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

输出:
0 2 3 3 40
*/

上一篇下一篇

猜你喜欢

热点阅读