*浙大PAT甲级 1087 dijkstra+dfs

由于输入的是城市名称,因此要先将名称与id想对应,可以用map映射。

dist数组代表源点到该点的最短路径,path数组记录推荐路径,num数组记录源点到该点的最大happy值。

通过dijkstra来得出最短路径以及最大happy值和相应路径。

但关键是怎么求有多少条总和为最短路径的路径数,这里可以通过得到的最短路径进行深度优先搜索。

AC代码:

#include<iostream>
#include<map>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<list>
#include<set>
#include<stack>
#include<cmath>
#include<vector>
#define ll long long
#define inf 999999999
using namespace std;
map<string,int> mm;
vector<string> vv;
int hap[220];
int a[200][200];
int mark[200];
int dist[200];
int path[200];
int num[200];
int ans=0;
int biaoji;
int n,k;
void dfs(int x,int now,int dis)
{
    if(x==biaoji&&now==dis)
    {
        ans++;
        return;
    }
    for(int i=0;i<n;i++)
    {
        if(mark[i]==0&&i!=x&&a[x][i]!=inf)
        {
            mark[i]=1;
            dfs(i,now+a[x][i],dis);
            mark[i]=0;
        }
    }
}
int main()
{
    string s;
    scanf("%d %d",&n,&k);
    cin>>s;
    mm[s]=0;
    vv.push_back(s);
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            a[i][j]=i==j?0:inf;
        }
    }
    for(int i=0;i<n-1;i++)
    {
        string tmp;
        int d;
        cin>>tmp;
        scanf("%d",&d);
        mm[tmp]=i+1;
        hap[i+1]=d;
        vv.push_back(tmp);
        if(tmp=="ROM")
        {
            biaoji=i+1;
        }
    }
    for(int i=0;i<k;i++)
    {
      string l,r;
      cin>>l>>r;
      int d;
      scanf("%d",&d);
      a[mm[l]][mm[r]]=a[mm[r]][mm[l]]=d;
    }
    for(int i=0;i<n;i++)
    {
        dist[i]=a[0][i];
        if(dist[i]!=inf)
        {
            num[i]=hap[i];
            path[i]=0;
        }
        else
        {
            path[i]=-1;
        }
    }
    path[0]=-1;
    mark[0]=1;
    for(int i=0;i<n-1;i++)
    {
        int minn=inf;
        int biao;
        for(int j=0;j<n;j++)
        {
            if(mark[j]==0&&dist[j]<minn)
            {
                minn=dist[j];
                biao=j;
            }
        }
        mark[biao]=1;
        for(int j=0;j<n;j++)
        {
            if(mark[j]==0)
            {
                if(dist[biao]+a[biao][j]<dist[j])
                {
                    dist[j]=dist[biao]+a[biao][j];
                    num[j]=num[biao]+hap[j];
                    path[j]=biao;
                }
                else if(dist[biao]+a[biao][j]==dist[j])
                {
                    if(num[biao]+hap[j]>num[j])
                    {
                        num[j]=num[biao]+hap[j];
                        path[j]=biao;
                    }
                }
            }
        }
    }
    int d=biaoji;
    //cout<<d<<endl;
    memset(mark,0,sizeof(mark));
    dfs(0,0,dist[biaoji]);
    vector<int> v;
    int dd=1;
    v.push_back(d);
    while(path[d]!=-1)
    {
        v.push_back(path[d]);
        dd++;
        d=path[d];
    }
    printf("%d %d %d %d\n",ans,dist[biaoji],num[biaoji],num[biaoji]/(dd-1));
    cout<<vv[v[dd-1]];
    for(int i=dd-2;i>=0;i--)
    {
        cout<<"->"<<vv[v[i]];
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值