PAT最短路 A1003 A1018 A1087(Dijkstra+DFS)

本文详细介绍了Dijkstra算法在解决最短路径问题中的应用,包括基本模版及其在多路径计数和最短路径优化问题上的实现。通过实例展示了如何结合DFS来处理更复杂的场景,并探讨了Dijkstra算法与地图路径规划、公共自行车管理和罗马道路连接等实际问题的结合。同时,文章还强调了Dijkstra算法与数据结构如map的有效配合。
摘要由CSDN通过智能技术生成

A1003 Emergency

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这题只要用到Dijkstra的模版即可
开辟数组w[maxn]记录到该点的最大权值
开辟数组num[maxn]记录到该点的最短路径条数(注意不要放错位置)

            if(G[u][v]!=INF&&vis[v]==false)
            {
                if(d[u]+G[u][v]<d[v])
                {
                    d[v]=d[u]+G[u][v];
                    w[v]=w[u]+weight[v];
                    num[v]=num[u];
                }
                else if(d[u]+G[u][v]==d[v])
                {
                    if(w[u]+weight[v]>w[v])
                    {
                        w[v]=w[u]+weight[v];
                    }
                    num[v]=num[v]+num[u];
                }
            }
 

完整代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=505;
const int INF=100000;
int n,m,c1,c2;

int G[maxn][maxn];
int vis[maxn]={false};
int w[maxn];
int weight[maxn];
int num[maxn];//表示起点s到达顶点u的最短路径条数
int d[maxn];

void Dijkstra(int s)
{
   fill(d,d+maxn,INF);
   fill(w,w+maxn,0);
   fill(num,num+maxn,0);
   d[s]=0;
   num[s]=1;
   w[s]=weight[s];

   for(int i=0;i<n;i++)
   {
       int u=-1,min=INF;
       for(int j=0;j<n;j++)
       {
           if(d[j]<min&&vis[j]==false)
           {
               u=j;
               min=d[j];
           }
       }

       if(u==-1) return;
       vis[u]=true;

       for(int v=0;v<n;v++)
       {
           if(G[u][v]!=INF&&vis[v]==false)
           {
               if(d[u]+G[u][v]<d[v])
               {
                   d[v]=d[u]+G[u][v];
                   w[v]=w[u]+weight[v];
                   num[v]=num[u];
               }
               else if(d[u]+G[u][v]==d[v])
               {
                   if(w[u]+weight[v]>w[v])
                   {
                       w[v]=w[u]+weight[v];
                   }
                   num[v]=num[v]+num[u];
               }
           }
       }
   }
   

}
int main()
{
   fill(G[0],G[0]+maxn*maxn,INF);
   scanf("%d%d%d%d",&n,&m,&c1,&c2);

   for(int i=0;i<n;i++)
   {
       scanf("%d",&weight[i]);
   }

   for(int i=0;i<m;i++)
   {
       int t1,t2;
       scanf("%d%d",&t1,&t2);
       scanf("%d",&G[t1][t2]);
       G[t2][t1]=G[t1][t2];
       
   }
   Dijkstra(c1);
   printf("%d %d",num[c2],w[c2]);



}

A1018 Public Bike Management

这题的“第二标尺”相比上一题而言复杂了许多,因此使用的是Dijkstra+DFS的做法

#include<bits/stdc++.h>
using namespace std;
const int maxn=505;
const int INF=100000;

int G[maxn][maxn];
int d[maxn];
bool vis[maxn]={false};
int Cmax,N,Sp,M;
int weight[maxn];

vector<int> pre[maxn];
int minNeed=INF,minRemain=INF;
vector<int> tempPath,path;
void Dijkstra(int s)
{
   fill(d,d+maxn,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)
           {
               MIN=d[j];
               u=j;

           }
       }
       if(u==-1) return;
       vis[u]=true;


       for(int v=0;v<=N;v++)
       {
           if(vis[v]==false&&G[u][v]!=INF)
           {
               if(d[v]>d[u]+G[u][v])
               {
                   d[v]=d[u]+G[u][v];
                   pre[v].clear();
                   pre[v].push_back(u);

               }
               else if(d[v]==d[u]+G[u][v])
               {
                   pre[v].push_back(u);                   
               }
              
           }

       }

   }
}


void DFS(int v)
{
   if(v==0) //如果递归到起点
   {
       tempPath.push_back(v);
       int need=0,remain=0; //计算这条路径的need和remain

       for(int i=tempPath.size()-1;i>=0;i--)
       {
           int id=tempPath[i];
           if(weight[id]>0)
           {
               remain+=weight[id];
           }
           else
           {
               if(remain>=abs(weight[id]))
               {
                   remain-=abs(weight[id]);
               }
               else
               {
                   need+=abs(weight[id])-remain;
                   remain=0;
               }
           }
       }
       if(need<minNeed) //如果发现这条路径的need或者remain更优,那么更新路径 path=tempPath
       {
           minNeed=need;
           minRemain=remain;
           path=tempPath;

       }
       else if(need==minNeed&&remain<minRemain)
       {
           minRemain=remain;
           path=tempPath;
       }
       tempPath.pop_back(); //起点处理完毕,pop,return
       return;
   }

   tempPath.push_back(v); //对pre进行深搜
   for(int i=0;i<pre[v].size();i++)
   {
       DFS(pre[v][i]);
   }
   tempPath.pop_back();
   

}


int main()
{
   fill(G[0],G[0]+maxn*maxn,INF);
   scanf("%d%d%d%d",&Cmax,&N,&Sp,&M);

   for(int i=1;i<=N;i++)
   {
       scanf("%d",&weight[i]);
       weight[i]=weight[i]-Cmax/2;
   }

   for(int i=0;i<M;i++)
   {
       int t1,t2;
       scanf("%d%d",&t1,&t2);
       scanf("%d",&G[t1][t2]);
       G[t2][t1]=G[t1][t2];
   }

   Dijkstra(0);
   DFS(Sp);
   
   printf("%d ",minNeed);
   for(int i=path.size()-1;i>=0;i--)
   {
       printf("%d",path[i]);
       if(i>0) printf("->");
       
   }
   printf(" %d",minRemain);
   return 0;
}

A1087 All Roads Lead to Rome

Dijkstra+DFS的终极模版,同时熟练了map的使用

#include<bits/stdc++.h>
using namespace std;
const int maxn=400;
const int INF=10000000;
int n,k;
string start;//起点城市
map<string,int> city2index;
map<int,string> index2city;
int numCity=1;
int weight[maxn];
int G[maxn][maxn];
int d[maxn];
int numPath=0;
int maxWeight=-INF;
double avgMaxWeight=-INF;
bool vis[maxn];
vector<int> pre[maxn];
vector<int> tempPath,path;


void c2i(string city)
{
    city2index[city]=numCity;
    index2city[numCity]=city;
    numCity++;
}

void Dijkstra(int s)
{
    fill(vis,vis+maxn,false);
    fill(d,d+maxn,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)
            {
                MIN=d[j];
                u=j;
            }
        }

        if(u==-1) return;
        vis[u]=true;

        for(int v=0;v<n;v++)
        {
            if(vis[v]==false&&G[u][v]!=INF)
            {
                if(d[v]>d[u]+G[u][v])
                {
                    d[v]=d[u]+G[u][v];
                    pre[v].clear();
                    pre[v].push_back(u);
                }
                else if(d[v]==d[u]+G[u][v])
                {
                    pre[v].push_back(u);
                }
            }

        }
    }


}


void DFS(int v)
{
    if(v==0)
    {
        tempPath.push_back(v);
        numPath++;
        int lengthPath=0; //记录路上有几个城市
        int tempWeight=0;
        double avgWeight=0;
        for(int i=tempPath.size()-2;i>=0;i--)
        {
            int id=tempPath[i];
            tempWeight+=weight[id];
            
        }
        lengthPath=tempPath.size()-1;
        avgWeight=1.0*tempWeight/lengthPath;

        if(tempWeight>maxWeight)
        {
            maxWeight=tempWeight;
            avgMaxWeight=avgWeight;
            path=tempPath;
        }
        else if(tempWeight==maxWeight)
        {
            if(avgWeight>avgMaxWeight)
            {
                avgMaxWeight=avgWeight;
                path=tempPath;
            }
        }

        tempPath.pop_back();
        return;
    }


    tempPath.push_back(v);

    for(int i=0;i<pre[v].size();i++)
    {
        DFS(pre[v][i]);
    }
    tempPath.pop_back();

}





int main()
{
    fill(G[0],G[0]+maxn*maxn,INF);
    scanf("%d%d",&n,&k);
    cin>>start;
    city2index[start]=0;
    index2city[0]=start;

    for(int i=1;i<=n-1;i++)
    {
        string city;
        int w;
        cin>>city>>w;
        c2i(city);
        weight[city2index[city]]=w;
    }

    for(int i=0;i<k;i++)
    {
        string c1,c2;
        cin>>c1>>c2;
        scanf("%d",&G[city2index[c1]][city2index[c2]]);
        G[city2index[c2]][city2index[c1]]=G[city2index[c1]][city2index[c2]];

    }
            Dijkstra(0);
        int ed=city2index["ROM"];
        DFS(ed);


        printf("%d %d %d %.0f\n",numPath,d[ed],maxWeight,avgMaxWeight);

        for(int i=path.size()-1;i>=0;i--)
        {
            cout<<index2city[path[i]];
            if(i!=0) printf("->");
        }
        return 0;



}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值