【PAT L2-001】最短路计数

给定一个无向带权网络,无负边,无重边和自环,每个顶点有一个正数权值。首先求特定原点s到终点d的最短路的个数;然后求所有最短路中顶点权值a[i]之和最大的那条,输出这条路径。

可用dijkstra算法求出所有最短路,用一个pathNum[u]数组记录从s到u的最短路的个数,查找链path[u]保存了到u为止使顶点权值a[i]之和最大的那条路径,sum[u]保存了这条路径的顶点权值和。

对于提交后的第3个测试点,注意更新新引入顶点u的邻居v的距离值dis[v]时,sum[v]无条件更新为sum[u]+a[v],因为要先满足最短路这个条件,得到的顶点才有意义。最短路更新,则sum要重新计算。

参考了博客 http://blog.csdn.net/tc_to_top/article/details/51427223

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <string>
  4 #include <iostream>
  5 #include <algorithm>
  6 #include <stack>
  7 #include <cmath>
  8 #define RINT(V) scanf("%d", &(V))
  9 #define FREAD() freopen("in.txt", "r", stdin)
 10 #define REP(N) for(int i=0; i<(N); i++)
 11 #define REPE(N) for(int i=1; i<=(N); i++)
 12 #define PINT(N) printf("%d", (N))
 13 #define PSTR(S) printf("%s", S)
 14 #define RSTR(S) scanf("%s", S)
 15 #define pn() printf("\n")
 16 #define pb(V) push_back(V)
 17 #define CLEAR(A, V) memset((A), (V), sizeof(A))
 18 using namespace std;
 19 typedef long long ll;
 20 const int MAX_N = 505;
 21 const int INF = 0x3fffffff;
 22
 23 int n, m, s, d;
 24 int a[MAX_N];
 25
 26 int V;
 27 int G[MAX_N][MAX_N];//邻接矩阵,无边是INF, 自己到自己是0
 28 int dis[MAX_N];//单源最短路数组
 29 int vis[MAX_N];
 30 int path[MAX_N], pathNum[MAX_N];
 31 int sum[MAX_N];
 32
 33 int shortest(){
 34     int minn = INF;
 35     int rt = -1;
 36     for(int v=0; v<n; v++){
 37         if(v == s) continue;
 38         if(!vis[v] && dis[v] < minn){
 39             minn = dis[v];
 40             rt = v;
 41         }
 42     }
 43     return rt;
 44 }
 45
 46 void dijkstra(){
 47     for(int v=0; v<n; v++){
 48         if(G[s][v] != INF && v != s){
 49             dis[v] = G[s][v];//一步直达
 50             path[v] = s;
 51             pathNum[v] = 1;
 52             sum[v] = a[s] + a[v];
 53         }
 54     }
 55     path[s] = -1;
 56     pathNum[s] = 1;
 57     vis[s] = 1;
 58     sum[s] = a[s];
 59     dis[s] = 0;
 60     while(1){
 61         int u = shortest();//select the next vertex
 62         if(u == -1) break;//no vertex left
 63         //cout << "choose " << u << endl;
 64         vis[u] = 1;
 65         for(int v=0; v<n; v++){//update priority
 66             if(vis[v]) continue;//只考虑Tk以外,即最短路尚未确定的点
 67             if(dis[v] > dis[u] + G[u][v]){
 68                 pathNum[v] = pathNum[u];
 69                 dis[v] = dis[u] + G[u][v];
 70                 path[v] = u;//记录前驱
 71                 sum[v] = sum[u] + a[v];//更新顶点上的权值和
 72             }else if(dis[v] == dis[u] + G[u][v]){//这部分是关键,同值不同解
 73                 //cout << "same " << u << endl;
 74                 pathNum[v] += pathNum[u];//|Tv| += |Tu| 这一步是关键
 75                 if(sum[v] < sum[u] + a[v]){
 76                     sum[v] = sum[u] + a[v];
 77                     path[v] = u;
 78                 }
 79             }
 80             //cout << "path[" << v << "] = " << path[v] << endl;
 81         }
 82     }
 83 }
 84
 85 void init(){
 86     for(int u=0; u<n; u++){
 87         for(int v=0; v<n; v++){
 88             G[u][v] = INF;
 89         }
 90         G[u][u] = 0;
 91         dis[u] = INF;
 92     }
 93     CLEAR(path, -1);
 94     CLEAR(pathNum, 0);
 95     CLEAR(sum, 0);
 96     CLEAR(vis, 0);
 97 }
 98
 99 int main()
100 {
101     FREAD();
102     scanf("%d%d%d%d", &n, &m, &s, &d);
103     init();
104     REP(n) RINT(a[i]);
105     REP(m){
106         int u, v, w;
107         scanf("%d%d%d", &u, &v, &w);
108         G[u][v] = min(G[u][v], w);//其实没有重边
109         G[v][u] = G[u][v];//邻接矩阵
110     }
111
112     dijkstra();//s为源, d为目的地
113     printf("%d %d\n", pathNum[d], sum[d]);
114
115     //输出路径
116     stack<int> sta;
117     int cur = d;
118     sta.push(cur);
119     while(cur != s){
120         cur = path[cur];
121         sta.push(cur);
122     }
123     while(sta.size() > 1){
124         printf("%d ", sta.top());
125         sta.pop();
126     }
127     printf("%d", sta.top());
128     return 0;
129 }

 

时间: 2024-08-02 20:00:07

【PAT L2-001】最短路计数的相关文章

求更新一个计数表(001 到 999)的java写法

问题描述 postgre里建了个计数表 count 里边只有一行一列 名叫counter的字段.目的就是计数,记录当前发行的counter数(范围在000到999之间的,但是是character型的)问题是:从表中取到counter 值后,如何用java程序写这个自增的循环的方法(999后再发行就是001)再把这个值改成 3位的字符串注意postgre里是 000 001 到999这样的字符型,先需要转换类型.谢谢--- 问题补充:qunbin123 写道 解决方案 public static

分布式Map中实现引用计数

前言 在<ReferenceCountSet无锁实现>中,详细介绍了如何在一个进程中实现一个无锁版本的ReferenceCountSet(或者说是在自己的代码里没有锁),但是最近遇到一个问题,如果是在分布式的环境中呢?如何实现这个引用计数?这个问题如果从头开始写,会是一个比较复杂的问题,在实际中,我们可以使用ZooKeeper设置时的version机制来实现,即CAS(Compare-And-Set).这是一个本人在实际项目中遇到的一个问题,但是会更简单一些,因为在我们的项目中,我们使用Gem

爱普生打印机废墨盒怎么计数清零?

  爱普生喷墨打印机使用时间长了,里面的墨盒计数一到规定的数值,机器就会停止打印,一开机,就出现所有警告灯闪亮,打印程序提示机器故障,联系维修员.怎么办呢,那只有清零才有正常了. 1.首先,要保证USB数据线正确连接到打印机,驱动程序正常,这两个是先决条件,否则不会成功.我们打开清零软件 2.双击Adjprog.exe进入 弹出如下菜单 3.按进入,进入以后按右上角的选择: 4.选择后面打印机对应的端口,比如USBX(R270).按OK 5.再点击"特定维修模式",进入下一步 6.进入

云计算用1.5KB内存为十亿对象计数方法

为了更好地理解已经明确基数的大数据集的挑战,我们假设你的日志文件包含16个字符的ID,并且你想统计不同ID的数量.例如: 4f67bfc603106cb2 这16个字符需要用128位来表示.6万5千个ID将需要1MB的空间.我们每天收到30多亿条事件记录,每条记录都有一个ID.这些ID需要3840亿位或45GB的存储.而这仅仅是ID字段需要的空间.我们采取一种简单的方法获取日常事件记录中以ID为基数的数据.最简单的办法就是使用哈希集合且存放到内存中,其中哈希集包含唯一ID的列表(即输入文件中可能

php引用计数与变量引用

每个php5.5变量都存储在一个叫做zval的变量容器中.   一个zval变量容器,除了包含变量的类型与值外,还包含两个字节的额外信息:   1.第一个是"is_ref",是个bool型,用来标识这个变量是否属于引用集合(reference set),若属于则其值为1,否则为0.   有个这个变量php引擎就能够将普通变量与引用变量区分开来.   2.第二个是"refcount",用来表示指向这个zval变量(符号)的个数.每个符号都有作用域(scope),那些主

网站流量统计杂谈—从计数到决策

网站流量统计程序是站长接触最多的程序之一,是网站运营必不可少的一项工具,各大网站流量统计程序网站居高的alexa值也体现出了站长们对网站流量统计的青睐. 最早的网站流量统计程序功能十分简单,利用数据库,有的甚至是服务器内存变量,统计下有几个人访问,刷新一次页面+1,好的话用session或者cookies做下简单的访问者区分.而直至现在,大部分网站流量统计程序仍然以计数为主要功能.这里面,51.la是计数型的访问统计程序中的优秀之作,单纯的网站流量记录功能,使用51.la均能很好地满足需求,而且

reference counting:PHP源码分析-变量的引用计数、写时复制(Reference counting &amp;amp; Copy-on-Write)

PHP语法中有两种赋值方式:引用赋值.非引用赋值.<?php$a = 1;$b = $a; // 非引用赋值$c = &$b; // 引用赋值从表面看,通常会这样认为:"引用赋值就是两个变量对应同一个变量(在C中其实就是一个zval),非引用赋值则是直接产生的一个新的变量(zval),同时将值copy过来".这种认为在大部分情况下都是可以想通的.(#1)但有些情况下则会显得非常低效,例如:(#2)<?phpfunction print_arr($arr){//非引用

浅谈引用计数

浅谈引用计数前言 作为Delphi程序员,您可以不用看这节内容,但是如果您想更多的了解一些COM内部技术,或是在对象模型与引用模型之间可以进行很好的控制的话,笔者更希望你可以抽出些许时间来看这一切的内容,而益处提体的将很明显,您可以自由的用一些技巧来解决让您头疼的问题.好了,继续我们今天的交流: 在组件技术必备知识二中,我们对接口(Interface)进行了一些介绍,当我们并没有深入的对接口的实现/效率/优化等问题进行进一步的禅述,而了解它们的确对于我们以后的编程是有很大的帮助的,我们都知道,每

Dreamweaver实现文章内容页的阅读计数

dreamweaver 有朋友问如何在DW中实现文章内容页的阅读计数,这方面网上相关的教程很多了,问的人多了,我索性结合"深度空间整站"程序代码,再写一遍操作流程. 操作之前先做一个文章系统的详细内容页,通过浏览网站页面可以看到了在文章列表页链接上给出了一个?fID_ArticleContent=xxx的参数来链接到详细内容页面ndex_Article_Content.asp.具体查阅一下相关资料,我就不废话了.操作步骤如下: 1.在DW中打开index_Article_Content