【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-10-28 18:49:36

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

HDU 1491 社交网络(最短路计数)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1491 题意:给出一个联通的无向图,边有权值.定义I(v)如下,计算每个点的I值. 思路:(1)最简单的就是那个floyd了...g[i][j]记录最短路长度,f[i][j]记录个数,不多说了: (2)下面说说我自己想出来的算法..枚举s和t,计算每个点到s和t的最短路..然后建立最短路树..之后求s到t的最短路个数..然后枚举删掉某个点再求最短路个数,则差值即为通过删掉点的最短路数目.

洛谷P1144 最短路计数(SPFA)

To 洛谷.1144 最短路计数 题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 输入第一行包含2个正整数N,M,为图的顶点数与边数. 接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边. 输出格式: 输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可.如果无法到达顶点i则输

洛谷 1144 最短路计数 bfs

洛谷1144 最短路计数 传送门 其实这道题目的正解应该是spfa里面加一些处理,,然而,,然而,,既然它是无权图,,那么就直接bfs了,用一个cnt记录一下每一个点的方案数,分几种情况讨论一下转移,最后输出cnt即为结果.. 题目中所说的重边和自环啥的没看出来有啥影响.. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int maxn = 100000 + 500;

【SPFA】 最短路计数

最短路计数 [问题描述]   给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. [输入格式]   输入第一行包含2个正整数N,M,为图的顶点数与边数. 接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边. [输出格式]   输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可.如果无法到达顶点i则输出0. [输入样

习题:最短路计数(SPFA最短路计数)

最短路计数(洛谷1144)题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条.输入输出格式输入格式:输入第一行包含2个正整数N,M,为图的顶点数与边数.接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边.输出格式:输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可.如果无法到达顶点i则输出0.输入输出样例输

最短路与次短路计数

poj  3464  http://poj.org/problem?id=3463 问最短路的条数+比最短路权值大 1  的条数 做法  比较一下次短路和最短路的值  若次短路恰好比最短路大1,答案为最短路+次短路条数,否则答案就是最短路条数 1 #include<cstdio> 2 const int inf=0x3f3f3f3f; 3 class Count_short_path { ///最短路与次短路计数Dijkstra_o(MV^2) 4 typedef int typec;///边

洛谷P1144 最短路计数 及其引申思考

图论题目练得比较少,发一道spfa的板子题目- 题目:P1144 题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 输入第一行包含2个正整数N,M,为图的顶点数与边数. 接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边. 输出格式: 输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的

题解——[JSOI2007]重要的城市 floyd:最短路计数

---题面--- 题解: 其实感觉还是比较妙的,第一眼看题想到floyd统计最短路条数, 注意到对于任意两点x,y而言,floyd将会枚举其最短路所可能经过的所有中转点, 因此我们可以直接分别统计对于所有二元组而言,最短路上必须经过的中转点, 最后遍历一次所有统计到的结果,并用bool数组标记一个地点是否被作为过中转点 最后再遍历一次bool数组,如果是中转点就输出即可 注意有多条最短路并不一定意味着这两个点之间的最短路就没有关键点, 因为这几条最短路可能有一个(或多个)共同用点,这时共同用点将

[图论]最短路计数(spfa)

最短路计数 Description 给出一个NN个顶点MM条边的无向无权图,顶点编号为1-N1−N.问从顶点11开始,到其他每个点的最短路有几条. Input 第一行包含22个正整数N,MN,M,为图的顶点数与边数. 接下来MM行,每行22个正整数x,yx,y,表示有一条顶点xx连向顶点yy的边,请注意可能有自环与重边. output 共NN行,每行一个非负整数,第ii行输出从顶点11到顶点ii有多少条不同的最短路,由于答案有可能会很大,你只需要输出ans \bmod 100003ansmod1