PAT甲级1003 Emergency

这道题是一道图论题,给我们n个城市,m条路,需要找到从起点到终点最短的路径有几条,并且从这些最短路径中输找到一条路径输出经过这条路径所有点权值和最大的值

我们采用dfs深度优先搜索,第一个k代表我们目前在哪个城市,第二个cost表明当前我们这条路径上的路径花费,第三个total表明当前路径的权值和

用一个f数组用来记录任意两个点之间的路径花费,如果没有的话那么就设为无穷大(我设为了0x3f3f3f3f),自身到自身路径我们也设为无穷大,因为害怕为了权值最大反复绕自己这个城市,其实我们经过一次之后这个城市的权值已经归0了,我们重复在一个城市绕圈是没有意义的,同时为了防止死循环,所以自己到自己的路径也设为无穷大

用一个布尔数组v来记录这个城市是否走过,最开始我们所在的城市直接设为1,我们在遍历时只找还没有访问过的城市,回到搜索过程,题目中要求在路径最短的情况下权值最大,所以搜索过程中如果我们当前的路径花费已经大于最短花费路径(代码中我用curcost代表最短花费路径的花费)直接返回,也就是搜索中经常使用的剪枝策略

如果搜索过程已经到了终点,首先判断当前路径花费是否小于最短路径的花费,如果小于最短路径花费,那么更新最短路径的花费,ans记录的是最短花费路径的数目,直接设为1,因为之前ans记录的是之前最短路径花费的数目,但是现在表明之前的路径不是最短路径,所以需要把ans置为1,因为目前的最短花费路径找到了一条,同时更新ansx,ansx记录的是最短花费路径所得到的权值,之前的路径不管权值多大都不是最短花费路径,所以我们需要舍去直接取当前最短花费路径的权值和

如果当前路径花费等于最短路径花费,那么ans++,表明最短路径的数目多了一个,同时在这里比较多条最短路径的权值,取全职最大的最短花费路径更新ansx

最后是dfs的初始调用,最开始在起始点,路径花费为0,权值加上当前起始点的权值即可

#include<cstdio>
#include<cstring>
using namespace std;
int a[505],f[505][505];
int n,curcost=1e9,ans,ansx,end;
bool v[505];
void dfs(int k,int cost,int total) {
    if(cost>curcost) return;
    if(k==end) {
        if(cost<curcost) {
            curcost=cost;
            ans=1;
            ansx=total;
        }
        else if(cost==curcost) {
            if(total>ansx) {
                ansx=total;
            }
            ans++;
        }
        return;
    }
    for(int i=0;i<n;i++) {
        if(f[k][i]!=0x3f3f3f3f&&!v[i]) {
            v[i]=true;
            dfs(i,cost+f[k][i],total+a[i]);
            v[i]=false;
        }
    }
}
int main() {
    int m,start;
    scanf("%d%d%d%d",&n,&m,&start,&end);
    for(int i=0;i<n;i++) {
        scanf("%d",&a[i]);
    }
    int x,y,z;
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=m;i++) {
        scanf("%d%d%d",&x,&y,&z);
        f[x][y]=f[y][x]=z;
    }
    v[start]=1;
    dfs(start,0,a[start]);
    printf("%d %d\n",ans,ansx);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值