• PAT


    Nothing to fear


    种一棵树最好的时间是十年前,其次是现在!

    那些你早出晚归付出的刻苦努力,你不想训练,当你觉的太累了但还是要咬牙坚持的时候,那就是在追逐梦想,不要在意终点有什么,要享受路途的过程,或许你不能成就梦想,但一定会有更伟大的事情随之而来。 mamba out~

    2020.7.13


    人一我十,人十我百,追逐青春的梦想,怀着自信的心,永不言弃!

    Emergency

    分析

    在Dijkstar得基础上记录到达某个点得最短路径得条数,以及点权最大值的方法

    1. 记录最短路条数

      记录路径条数得方法: 设置一个num数组,令num[strat] = 1;

      1.1 当在某个点x - > y 满足 dis[y] > dis[x] + w (w 表示 x- > y 得边权)

    此时需要更新最短路所以 num[y] = num[x]
    if(dis[y] > dis[x] + w)
    {
        num[y] = num[x];
    }
    

    1.2 当在某个点x - > y 满足 dis[y] == dis[x] + w (w 表示 x- > y 得边权)

    此时到达 y 得最短路径条数等于先前到达 y 得路径条数 + 到达 x 点得路径条数
    即 num[y] = num[y] + num[x]
    if(dis[y] == dis[x] + w)
    {
        num[y] = num[x] + num[y];
    }
    
    1. 记录最大点权

      我们设置一个数组 w 来记录到达每个点得可以携带得最大点权时多少

      首先令w[start] = weight[start]

      2.1 当在某个点x - > y 满足 dis[y] > dis[x] + w (w 表示 x- > y 得边权)

    if(dis[y] > dis[x] + w)
    {
    	num[y] = num[x];
    	w[y] = w[x] + weight[y]; // 直接更新w[y]
    }
    

    2.2 当在某个点x - > y 满足 dis[y] == dis[x] + w (w 表示 x- > y 得边权)

    if(dis[y] == dis[x] + w)
    {
    	num[y] = num[x] + num[y];
    	w[y] = max(w[y] , w[x] + wight[y]) // 取得所有最短路径中可携带点权最大得那一个
    }
    
    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    
    using namespace std;
    const int N = 25005;
    struct edge{
    	int to, next, w;
    }e[N];
    int head[N] , tot = 1, weight[N];
    bool vis[N];
    int n , m , s , t;
    int dis[N] , ans[N] , num[N];
    void add(int a, int b, int w)
    {
    	e[tot].w = w;
    	e[tot].to = b;
    	e[tot].next = head[a];
    	head[a] = tot++;
    }
    void Dijkstra(int s)
    {
    	memset(dis , 0x3f , sizeof dis);
    	memset(vis , 0 , sizeof vis);
    	dis[s] = 0;ans[s] = weight[s];num[s] = 1;
    	// 首先找到一个距离最短的点放入集合中
    	for(int k = 0;k < n - 1;k ++)
    	{
    		int x = -1;
    		for(int i = 0;i < n;i ++)
    		{
    			if(!vis[i] && (x == -1 || dis[i] < dis[x]))
    				x = i;
    		}
    		if(x == -1)break;
    		vis[x] = 1;
    		for(int i = head[x]; i ;i = e[i].next)
    		{
    			int y = e[i].to, w = e[i].w;
    			if(vis[y])continue;
    			if(dis[y] > dis[x] + w)
    			{
    				dis[y] = dis[x] + w;
    				num[y] = num[x];
    				ans[y] = ans[x] + weight[y]; 
    			}
    			else if(dis[y] == dis[x] + w)
    			{
    				num[y] = num[y] + num[x];
    				ans[y] = max(ans[y],ans[x] + weight[y]);
    			}
    		}
    	}
    }
    int main()
    {
    	cin >> n >> m >> s >> t;
    	for(int i = 0;i < n ;i ++)
    		scanf("%d",&weight[i]);
    	int a , b , c;
    	for(int i = 0;i < m;i ++)
    	{
    		scanf("%d %d %d",&a , &b , &c);
    		add(a , b , c);add(b , a , c);
    	}
    	Dijkstra(s);
    	cout << num[t] << " " << ans[t] << endl;
    	return 0;
    }
    
  • 相关阅读:
    第四次实验报告
    第三次实验报告
    循环结构课后反思
    第二次实验报告
    第一次实验报告1
    第一次作业
    第二次实验报告 总结
    第九章实验报告
    第八章实验报告
    第六次实验报告
  • 原文地址:https://www.cnblogs.com/wlw-x/p/13295086.html
Copyright © 2020-2023  润新知