l3直捣黄龙

本题为三元素最短路,路径为第一元素,到起始点的节点数为第二元素,过程中的敌军数量和为第三元素

本题以字符串作为节点编号,可以用map映射成数字编号节点便于操作,结果要求输出最终路径,所以需要一个记录每个节点的前驱数组

而结果路径输出是按照字符串输出,所以还需要一个反映射map便于根据数字编号节点输出字符串编号节点

​
#include <bits/stdc++.h>
#define endl '\n'
#define INF 0x3f3f3f3f
#define ll long long
#define Mirai ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#define COUT cout << "###" << endl;
#define pb push_back
using namespace std;
typedef pair<int,int> PII;
const int N=220;
struct Edge
{
    int v,w,num;
};
vector<Edge> g[N];
map<string,int> mp;//映射map
map<int,string> ump;//反映射map
int a[N];//存储每个点的敌军数
int dist[N];//最短距离
bool vis[N];
int cnt[N];//最短路径条数
int d[N];//距离起点距离多少个城镇
int path[N];//前驱节点
int sum[N];
int n,m,idx;
string s,t;
void dij()
{
    dist[mp[s]]=0;
    cnt[mp[s]]=1;
    path[mp[s]]=mp[s];
    sum[mp[s]]=0;
    priority_queue<PII,vector<PII>,greater<PII>> q;
    q.push({dist[mp[s]],mp[s]});
    while(q.size())
    {
        int u=q.top().second;
        q.pop();
        if(vis[u])continue;
        vis[u]=true;
        for(auto [v,w,num]:g[u])
        {
            if(dist[v]>dist[u]+w)
            {
                dist[v]=dist[u]+w;
                d[v]=d[u]+1;
                cnt[v]=cnt[u];
                path[v]=u;
                sum[v]=sum[u]+num;
                q.push({dist[v],v});
            }
            else if(dist[v]==dist[u]+w)
            {
                if(d[v]<d[u]+1)
                {
                    d[v]=d[u]+1;
                    path[v]=u;
                    sum[v]=sum[u]+num;
                    q.push({dist[v],v});
                }
                else if(d[v]==d[u]+1)
                {
                    if(sum[v]<sum[u]+num)
                    {
                        sum[v]=sum[u]+num;
                        path[v]=u;
                        q.push({dist[v],v});
                    }
                }
                cnt[v]+=cnt[u];
            }
        }
    }
}
void Print(int u)
{
    if(path[u]!=u)
    {
        Print(path[u]);
        cout<<"->"<<ump[u];
        return ;
    }
    cout<<ump[u];
}
int main()
{
    cin>>n>>m>>s>>t;
    idx=0;
    mp[s]=++idx;//起点编号为1
    ump[idx]=s;
    for(int i=1;i<=n;i++)
    {
        dist[i]=INF;
    }
    for(int i=2;i<=n;i++)
    {
        string adr;
        int x;
        cin>>adr>>x;
        mp[adr]=++idx;
        ump[idx]=adr;
        a[idx]=x;
    }
    for(int i=0;i<m;i++)
    {
        string u,v;
        int w;
        cin>>u>>v>>w;
        g[mp[u]].push_back({mp[v],w,a[mp[v]]});
        g[mp[v]].push_back({mp[u],w,a[mp[u]]});
    }
    dij();
    Print(mp[t]);
    cout<<endl;
    cout<<cnt[mp[t]]<<" "<<dist[mp[t]]<<" "<<sum[mp[t]];
    return 0;
}

​

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值