vector存储图,Dijkstra常见题型:在保证路径最短基础上新增边权,新增点权以及求解最短路径条数

1.这是解决三种问题的第一种方法

例题描述:
pat1003
本题只是要求三种问题中的新增点权(每个城市的救援小组数目)和最短路径条数,再次基础上把新增边权的我也加上了,即每条边的花费。

其中把无向边当作两条方向相反的有向边存储,用vector数组实现链表存储
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <string.h>
using namespace std;
const int INF = 0x3fffffff;
const int maxn = 1e3+10;

struct Node{
    
    
    int adjvex;
    int edge_weight;
    int spend;
};
Node node;
vector<Node> Agraph[maxn];
bool visit[maxn] = {
    
    0};//遍历结点记忆数组
int  min_dis[maxn];//min_dis[u]:意思是从开始节点到u的最短距离
int  path[maxn];//存储从开始结点到某点的最短路径,用递归输出
int  rescue_num[maxn] = {
    
    0};//各个城市的救援小组数目
//注意:下面两个要求的东西得先满足时最短路径再说
int  rescue_nummax[maxn] = {
    
    0};//rescue_nummax[u]:意思是从开始节点到u的所有的最短路径中的最大救援小组数目
int  route_num[maxn] = {
    
    0};//route_num[u]:意思是从开始节点到u的路径条数
vector<Node> Agraph_spend[maxn];//存储花费
int  min_spend[maxn] = {
    
    0};//min_spend[u]:意思是从开始节点到u的所有的最短路径中的最少花费

int  n,m;
void Dijkstra(int v)
{
    
    
    fill(min_dis,min_dis + n,INF);
    min_dis[v] = 0;
    fill(min_spend,min_spend + n,INF);
    min_spend[v] = 0;
    rescue_nummax[v] = rescue_num[v];
    route_num[v] = 1;
    for(int i = 0;i < n;i++)
    {
    
    
        path[i] = i;
    }
    for(int i = 0;i < n;i++)
    {
    
    
        int u = -1,MIN = INF;
        for(int j = 0;j < n;j++)
        {
    
    
            if(visit[j] == false&&min_dis[j] < MIN)
            {
    
    
                u = j;
                MIN = min_dis[j];
            }
        }
        if(u == -1) return;
        visit[u] = true;
        for(int j = 0;j < (int)Agraph[u].size();j++)//u->j
        {
    
    
            node = Agraph[u][j];
            if(visit[node.adjvex] == false)
            {
    
    
                if(min_dis[u] + node.edge_weight < min_dis[node.adjvex])
                {
    
    
                    min_dis[node.adjvex] = min_dis[u] + node.edge_weight;
                    path[node.adjvex] = u;
                    rescue_nummax[node.adjvex] = rescue_nummax[u] + rescue_num[node.adjvex];
                    route_num[node.adjvex] = route_num[u];
                    min_spend[node.adjvex] = min_spend[u] + node.spend;
                }else if(min_dis[u] + node.edge_weight == min_dis[node.adjvex]){
    
    
                    route_num[node.adjvex] += route_num[u];
                    if(rescue_nummax[u] + rescue_num[node.adjvex] > rescue_nummax[node.adjvex])
                        rescue_nummax[node.adjvex] = rescue_nummax[u] + rescue_num[node.adjvex];
                    if(min_spend[u] + node.spend < min_spend[node.adjvex])
                    {
    
    
                        min_spend[node.adjvex] = min_spend[u] + node.spend;
                        path[node.adjvex] = u;
                    }
                }
            }
        }
    }
}
void DFS_path(int start,int v)
{
    
    
    if(start == v)
    {
    
    
        cout<<start;
        return;
    }
    else{
    
    
        DFS_path(start,path[v]);
        cout<<" "<<v;
    }
}
int main()
{
    
    
    ios::sync_with_stdio(false);
    cin.tie(0);
    int vex1,vex2,weight,start,i,end,spend;
    cin>>n>>m>>start>>end;
    for(i = 0;i < n; i++)
        cin>>rescue_num[i];
    for(i = 0 ;i < m;i++)
    {
    
    
        cin>>vex1>>vex2>>weight>>spend;
        node.adjvex = vex2;
        node.spend = spend;
        node.edge_weight = weight;
        Agraph[vex1].push_back(node);
        node.adjvex = vex1;
        node.spend = spend;
        node.edge_weight = weight;
        Agraph[vex2].push_back(node);
    }
    Dijkstra(start);
    cout<<route_num[end]<<" "<<rescue_nummax[end]<<" "<<min_spend[end]<<endl;
    DFS_path(start,end);
    return 0;
}

2 .测试用例:

5 6 0 2
1 2 1 5 3
0 1 1 3
0 2 2 1
0 3 1 1
1 2 1 5
2 4 1 1
3 4 1 1
上述代码path中保存的最短路径是保证最小花费(新增的边权)的那条最短路径,若想求得最大营救小组数目的最短路径,只需将

 if(rescue_nummax[u] + rescue_num[node.adjvex] > rescue_nummax[node.adjvex])
    rescue_nummax[node.adjvex] = rescue_nummax[u] + rescue_num[node.adjvex];
 if(min_spend[u] + node.spend < min_spend[node.adjvex])
 {
    
    
     min_spend[node.adjvex] = min_spend[u] + node.spend;
     path[node.adjvex] = u;
 }

替换为

 if(rescue_nummax[u] + rescue_num[node.adjvex] > rescue_nummax[node.adjvex])
 {
    
    
     rescue_nummax[node.adjvex] = rescue_nummax[u] + rescue_num[node.adjvex];
     path[node.adjvex] = u;
 }
if(min_spend[u] + node.spend < min_spend[node.adjvex])
    min_spend[node.adjvex] = min_spend[u] + node.spend;

3.第二类方法:先说新增点权的路径数目

即用vector数组型的pre存储某个点的对应多个最短路径的前驱。如本题的前驱关系及pre如下:
在这里插入图片描述可以看出最短路径的最后一个点都是开始点。

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <string.h>
using namespace std;
const int INF = 0x3fffffff;
const int maxn = 1e3+10;

struct Node{
    
    
    int adjvex;
    int edge_weight;
};
Node node;
vector<Node> Agraph[maxn];
bool visit[maxn] = {
    
    0};
int  min_dis[maxn];//min_dis[u]:意思是从开始节点到u的最短距离
int  rescue_num[maxn];
vector<int> pre[maxn];
vector<int> path,temp;
int  n,m,route_num = 0,max_value = 0;
void Dijkstra(int v)
{
    
    
    fill(min_dis,min_dis + n,INF);
    min_dis[v] = 0;
    for(int i = 0;i < n;i++)
    {
    
    
        int u = -1,MIN = INF;
        for(int j = 0;j < n;j++)
        {
    
    
            if(visit[j] == false&&min_dis[j] < MIN)
            {
    
    
                u = j;
                MIN = min_dis[j];
            }
        }
        if(u == -1) return;
        visit[u] = true;
        for(int j = 0;j < (int)Agraph[u].size();j++)//u->j
        {
    
    
            node = Agraph[u][j];
            if(visit[node.adjvex] == false)
            {
    
    
                if(min_dis[u] + node.edge_weight < min_dis[node.adjvex])
                {
    
    
                    min_dis[node.adjvex] = min_dis[u] + node.edge_weight;
                    pre[node.adjvex].clear();
                    pre[node.adjvex].push_back(u);
                }else if(min_dis[u] + node.edge_weight == min_dis[node.adjvex]){
    
    
                    pre[node.adjvex].push_back(u);
                }
            }
        }
    }
}
void DFS(int start,int v)
{
    
    
    if(v == start)
    {
    
    
        route_num++;
        temp.push_back(v);
        int value = 0;
        for(int i = temp.size()-1;i >= 0; i--)
        {
    
    
            value += rescue_num[temp[i]];
        }
        if(value > max_value)
        {
    
    
            max_value = value;
            path = temp;
        }
        temp.pop_back();
        return;

    }else{
    
    
        temp.push_back(v);
        for(int i = 0;i < (int)pre[v].size();i++)
            DFS(start,pre[v][i]);
        temp.pop_back();
    }
}
int main()
{
    
    
    ios::sync_with_stdio(false);
    cin.tie(0);
    int vex1,vex2,weight,start,i,end,spend;
    cin>>n>>m>>start>>end;
    for(i = 0;i < n; i++)
        cin>>rescue_num[i];
    for(i = 0 ;i < m;i++)
    {
    
    
        cin>>vex1>>vex2>>weight;
        node.adjvex = vex2;
        node.edge_weight = weight;
        Agraph[vex1].push_back(node);
        node.adjvex = vex1;
        node.edge_weight = weight;
        Agraph[vex2].push_back(node);
    }
    Dijkstra(start);
    DFS(start,end);
    cout<<route_num<<" "<<max_value;
    return 0;
}

再来一个题:新增边权

pat1030

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <string.h>
using namespace std;
const int INF = 0x3fffffff;
const int maxn = 1e3+10;

struct Node{
    
    
    int adjvex;
    int edge_weight;
    int spend;
};
Node node;
vector<Node> Agraph[maxn];
bool visit[maxn] = {
    
    0};
int  min_dis[maxn];//min_dis[u]:意思是从开始节点到u的最短距离
int  rescue_num[maxn];
vector<int> pre[maxn];
vector<int> path,temp;
int  n,m,min_value = INF;
void Dijkstra(int v)
{
    
    
    fill(min_dis,min_dis + n,INF);
    min_dis[v] = 0;
    for(int i = 0;i < n;i++)
    {
    
    
        int u = -1,MIN = INF;
        for(int j = 0;j < n;j++)
        {
    
    
            if(visit[j] == false&&min_dis[j] < MIN)
            {
    
    
                u = j;
                MIN = min_dis[j];
            }
        }
        if(u == -1) return;
        visit[u] = true;
        for(int j = 0;j < (int)Agraph[u].size();j++)//u->j
        {
    
    
            node = Agraph[u][j];
            if(visit[node.adjvex] == false)
            {
    
    
                if(min_dis[u] + node.edge_weight < min_dis[node.adjvex])
                {
    
    
                    min_dis[node.adjvex] = min_dis[u] + node.edge_weight;
                    pre[node.adjvex].clear();
                    pre[node.adjvex].push_back(u);
                }else if(min_dis[u] + node.edge_weight == min_dis[node.adjvex]){
    
    
                    pre[node.adjvex].push_back(u);
                }
            }
        }
    }
}
void DFS(int start,int v)
{
    
    
    if(v == start)
    {
    
    
        temp.push_back(v);
        int value = 0;
        for(int i = temp.size()-1;i > 0; i--)
        {
    
    
            int id = temp[i],idnext = temp[i - 1];
            for(int j = 0;j < (int)Agraph[id].size();j++)
            {
    
    
                if(Agraph[id][j].adjvex == idnext)
                {
    
    
                    value += Agraph[id][j].spend;
                    break;
                }
            }
        }
        if(value < min_value)
        {
    
    
            min_value = value;
            path = temp;
        }
        temp.pop_back();
        return;

    }else{
    
    
        temp.push_back(v);
        for(int i = 0;i < (int)pre[v].size();i++)
            DFS(start,pre[v][i]);
        temp.pop_back();
    }
}
int main()
{
    
    
    ios::sync_with_stdio(false);
    cin.tie(0);
    int vex1,vex2,weight,start,i,end,spend;
    cin>>n>>m>>start>>end;
    for(i = 0 ;i < m;i++)
    {
    
    
        cin>>vex1>>vex2>>weight>>spend;
        node.adjvex = vex2;
        node.spend  = spend;
        node.edge_weight = weight;
        Agraph[vex1].push_back(node);
        node.adjvex = vex1;
        node.edge_weight = weight;
        node.spend  = spend;
        Agraph[vex2].push_back(node);
    }
    Dijkstra(start);
    DFS(start,end);
    for(i = path.size() - 1;i >= 0;i--)
    {
    
    
        cout<<path[i]<<" ";
    }
    cout<<min_dis[end]<<" "<<min_value;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44142774/article/details/113782943