好像原题是这个?https://www.cnblogs.com/kanchuang/p/11120052.html

这个有解释:https://blog.csdn.net/wddwjlss/article/details/82081754

原题是这个:https://www.luogu.org/problem/P1144

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; const int MOD = 1e5 + 3, MAXN = 1e6 + 5;
const int INF = 1e9; vector<int> e[MAXN];
inline void add_edge(int u, int v) {
e[u].emplace_back(v);
e[v].emplace_back(u);
} bool vis[MAXN];
int dis[MAXN], ans[MAXN];
priority_queue<pair<int, int> > pq; void Dijkstra(int n, int s) {
for(int i = 1; i <= n; i++)
dis[i] = INF;
dis[s] = 0, ans[s] = 1, pq.push({0, s});
while(!pq.empty()) {
int u = pq.top().second;
pq.pop();
if(vis[u])
continue;
vis[u] = 1;
for(auto v : e[u]) {
if(!vis[v] && dis[v] > dis[u] + 1) {
dis[v] = dis[u] + 1;
ans[v] = ans[u];
pq.push({-dis[v], v});
} else if(!vis[v] && dis[v] == dis[u] + 1) {
ans[v] = (ans[v] + ans[u]) % MOD;
}
}
}
} int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
add_edge(u, v);
}
Dijkstra(n, 1);
for(int i = 1; i <= n; ++i)
printf("%d\n", ans[i]);
}

询问从1节点开始的最短路的种类数。

首先连接两个点之间的不是最短的路一定是没有用的。所以至多每种d就n/d条边,同样的直接叠加条数,计数时乘法叠加路径数。

在dijkstra的同时,要是更新了就清空,否则相等就继续计数。

图论知识太缺乏。

哈哈哈我居然能过!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; const int INF = 0x3f3f3f3f; const int MAXN = 5e4 + 5;
const int MAXM = 1400000 + 5; struct Edge {
int v, w, k, next;
Edge(int v = 0, int w = 0, int k = 0): v(v), w(w), k(k) {}
}; int cnt_edge;
int head[MAXN];
Edge edge[MAXM]; inline void init_graph(int n) {
cnt_edge = 0;
memset(head + 1, 0, sizeof(head[0])*n);
} inline void add_edge(int u, int v, int w, int k) {
cnt_edge++;
edge[cnt_edge].v = v;
edge[cnt_edge].w = w;
edge[cnt_edge].k = k;
edge[cnt_edge].next = head[u];
head[u] = cnt_edge;
} bool vis[MAXN];
int dis[MAXN];
int ans[MAXN]; struct Edge_node {
int v, w;
Edge_node(int v = 0, int w = 0): v(v), w(w) {}
bool operator<(const Edge_node &e)const {
return w > e.w;
}
}; const int MOD = 1e9 + 9; void Dijkstra(int n, int s) {
memset(vis + 1, 0, sizeof(vis[0])*n);
for(int i = 1; i <= n; i++)
dis[i] = INF;
priority_queue<Edge_node> pq;
dis[s] = 0;
ans[s] = 1;
pq.push(Edge_node(s, 0));
while(!pq.empty()) {
int u = pq.top().v;
pq.pop();
if(vis[u])
continue;
vis[u] = 1;
for(int i = head[u]; i; i = edge[i].next) {
int &v = edge[i].v;
int &w = edge[i].w;
if(!vis[v] && dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
ans[v] = 1ll * ans[u] * edge[i].k % MOD;
pq.push(Edge_node(v, dis[v]));
} else if(!vis[v] && dis[v] == dis[u] + w) {
ans[v] = (ans[v] + 1ll * ans[u] * edge[i].k % MOD) % MOD;
}
}
}
} int minw[MAXN];
int minw2[MAXN];
int dk[MAXN];
int dk2[MAXN]; int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n, m, q;
scanf("%d%d%d", &n, &m, &q); for(int i = 1; i <= m; i++) {
int d, v, w;
scanf("%d%d%d", &d, &v, &w);
if(v == 1) {
if(minw[d] == 0 || minw[d] > w) {
minw[d] = w;
dk[d] = 1;
} else if(minw[d] == w) {
++dk[d];
}
} else {
if(minw2[d] == 0 || minw2[d] > w) {
minw2[d] = w;
dk2[d] = 1;
} else if(minw2[d] == w) {
++dk2[d];
}
}
}
init_graph(n);
for(int d = 1; d <= n; d++) {
if(minw[d]) {
for(int v = 1; v <= n; v += d) {
if(v + d <= n) {
add_edge(v, v + d, minw[d], dk[d]);
add_edge(v + d, v, minw[d], dk[d]);
}
}
}
}
for(int d = 1; d <= n; d++) {
if(minw2[d]) {
for(int v = n; v >= 1; v -= d) {
if(v - d >= 1) {
add_edge(v - d, v, minw2[d], dk2[d]);
add_edge(v, v - d, minw2[d], dk2[d]);
}
}
}
}
Dijkstra(n, 1);
for(int i = 1; i <= q; ++i) {
int x, y;
scanf("%d%d", &x, &y);
printf("%d\n", ans[y]);
}
}

有点bug,dis应该是ll才对的。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; const int MOD = 1e9 + 9, MAXN = 5e4 + 5, MAXM = 1400000 + 5;
const ll INF = 1e18;
struct Edge {
int v, w, k, next;
Edge(int v = 0, int w = 0, int k = 0): v(v), w(w), k(k) {}
}; int h[MAXN], etop;
Edge e[MAXM]; inline void init_graph(int n) {
etop = 0;
memset(h + 1, 0, sizeof(h[0])*n);
} inline void add_edge(int u, int v, int w, int k) {
e[++etop] = Edge(v, w, k);
e[etop].next = h[u];
h[u] = etop;
} bool vis[MAXN];
ll dis[MAXN];
int ans[MAXN];
priority_queue<pair<ll, int> > pq; void Dijkstra(int n, int s) {
//vis pq
for(int i = 1; i <= n; i++)
dis[i] = INF;
dis[s] = 0, ans[s] = 1, pq.push({0, s});
while(!pq.empty()) {
int u = pq.top().second;
pq.pop();
if(vis[u])
continue;
vis[u] = 1;
for(int i = h[u]; i; i = e[i].next) {
int &v = e[i].v, &w = e[i].w;
if(!vis[v] && dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
ans[v] = 1ll * ans[u] * e[i].k % MOD;
pq.push({-dis[v], v});
} else if(!vis[v] && dis[v] == dis[u] + w) {
ans[v] = (ans[v] + 1ll * ans[u] * e[i].k % MOD) % MOD;
}
}
}
} int minw[MAXN], minw2[MAXN], dk[MAXN], dk2[MAXN]; int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n, m, q;
scanf("%d%d%d", &n, &m, &q);
for(int i = 1; i <= m; i++) {
int d, v, w;
scanf("%d%d%d", &d, &v, &w);
if(v == 1) {
if(minw[d] == 0 || minw[d] > w) {
minw[d] = w;
dk[d] = 1;
} else if(minw[d] == w)
++dk[d];
} else {
if(minw2[d] == 0 || minw2[d] > w) {
minw2[d] = w;
dk2[d] = 1;
} else if(minw2[d] == w)
++dk2[d];
}
}
init_graph(n);
for(int d = 1; d <= n; d++) {
if(minw[d]) {
for(int v = 1; v <= n; v += d) {
if(v + d <= n) {
add_edge(v, v + d, minw[d], dk[d]);
add_edge(v + d, v, minw[d], dk[d]);
}
}
}
if(minw2[d]) {
for(int v = n; v >= 1; v -= d) {
if(v - d >= 1) {
add_edge(v - d, v, minw2[d], dk2[d]);
add_edge(v, v - d, minw2[d], dk2[d]);
}
}
}
}
Dijkstra(n, 1);
for(int i = 1; i <= q; ++i) {
int x, y;
scanf("%d%d", &x, &y);
printf("%d\n", ans[y]);
}
}

来个vector版的比一比。

感觉差不多,好像vector挺方便的。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; const int MOD = 1e9 + 9, MAXN = 5e4 + 5;
const ll INF = 1e18; struct Edge {
int v, w, k;
Edge(int v = 0, int w = 0, int k = 0): v(v), w(w), k(k) {}
}; vector<Edge> e[MAXN];
inline void add_edge(int u, int v, int w, int k) {
e[u].emplace_back(v, w, k);
e[v].emplace_back(u, w, k);
} bool vis[MAXN];
ll dis[MAXN];
int ans[MAXN];
priority_queue<pair<ll, int> > pq; void Dijkstra(int n, int s) {
//vis pq
for(int i = 1; i <= n; i++)
dis[i] = INF;
dis[s] = 0, ans[s] = 1, pq.push({0, s});
while(!pq.empty()) {
int u = pq.top().second;
pq.pop();
if(vis[u])
continue;
vis[u] = 1;
for(auto ei : e[u]) {
int v = ei.v, w = ei.w, k = ei.k;
if(!vis[v] && dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
ans[v] = 1ll * ans[u] * k % MOD;
pq.push({-dis[v], v});
} else if(!vis[v] && dis[v] == dis[u] + w) {
ans[v] = (ans[v] + 1ll * ans[u] * k % MOD) % MOD;
}
}
}
} int minw[MAXN], minw2[MAXN], dk[MAXN], dk2[MAXN]; int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n, m, q;
scanf("%d%d%d", &n, &m, &q);
for(int i = 1; i <= m; i++) {
int d, v, w;
scanf("%d%d%d", &d, &v, &w);
if(v == 1) {
if(minw[d] == 0 || minw[d] > w) {
minw[d] = w;
dk[d] = 1;
} else if(minw[d] == w)
++dk[d];
} else {
if(minw2[d] == 0 || minw2[d] > w) {
minw2[d] = w;
dk2[d] = 1;
} else if(minw2[d] == w)
++dk2[d];
}
}
for(int d = 1; d <= n; d++) {
if(minw[d])
for(int v = 1; v + d <= n; v += d)
add_edge(v, v + d, minw[d], dk[d]);
if(minw2[d])
for(int v = n; v - d >= 1; v -= d)
add_edge(v - d, v, minw2[d], dk2[d]);
}
Dijkstra(n, 1);
for(int i = 1; i <= q; ++i) {
int x, y;
scanf("%d%d", &x, &y);
printf("%d\n", ans[y]);
}
}

SCUT - 486 - 无向图上的点 - Dijkstra的更多相关文章

  1. 图上最短路(Dijkstra, spfa)

    单源最短路径 题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包含三个整数N.M.S,分别表示点的个数.有向边的个数.出发点的编号. 接下来 ...

  2. SCUT - 483 - 数轴上的点

    https://scut.online/p/483 改了题目之后发现,其实n个点放在[1,2N],要求间距至少是2,那么有且只有一个点和前面点的间距是3(设-1存在一个点),其他点的间距都必须是2.排 ...

  3. SCUT - 484 - 平面上的点 - 数据结构

    https://scut.online/p/484 一开始想的是按固定斜率的直线从无穷扫下来,但是一直都WA,不知道是哪里错了还是精度问题? #include<bits/stdc++.h> ...

  4. 关于scut在unity上的主动推送

    自带的samples里面,chat的例子涉及主动推送,可作为参考. 在unity里面接收主动推送用Net.CommonCallback 服务端最近的新版本更改了接口,有两种方法推送: ActionFa ...

  5. 在加权无向图上求出一条从1号结点到N号结点的路径,使路径上第K+1大的边权尽量小

    二分+最短路算法 #include<cstdio> #include<iostream> #include<cstring> #include<algorit ...

  6. UVa 10801 - Lift Hopping(dijkstra最短路)

    根据题意,以每一层楼为顶点,每个电梯可以到达的两层楼之间的秒数为每一条边的权值,以此构建一个无向图.然后利用dijkstra求出最短的时间,注意每次换乘电梯需要等待60s(因为同一个电梯上的楼层是相互 ...

  7. 最短路径算法——Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson

    根据DSqiu的blog整理出来 :http://dsqiu.iteye.com/blog/1689163 PS:模板是自己写的,如有错误欢迎指出~ 本文内容框架: §1 Dijkstra算法 §2 ...

  8. hdu 1874 Dijkstra算法

    先贴个网上找的比较通俗易懂的教程: 2.1Dijkstra算法(非负权,使用于有向图和无向图) Dijkstra算法是典型最短路算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心 ...

  9. UVA5135 Mining Your Own Business ( 无向图双连通分量)

    题目链接 题意:n条隧道由一些点连接而成,其中每条隧道链接两个连接点.任意两个连接点之间最多只有一条隧道.任务就是在这些连接点中,安装尽量少的太平井和逃生装置,使得不管哪个连接点倒塌,工人都能从其他太 ...

随机推荐

  1. 用户输入和while 循环

    input 工作原理 函数input()让程序暂停运行,等待用户输入一些文本.获取用户输入后,Python将其存储在一个变量中. message = input("need to input ...

  2. scrapy项目2:爬取智联招聘的金融类高端岗位(spider类)

    ---恢复内容开始--- 今天我们来爬取一下智联招聘上金融行业薪酬在50-100万的职位. 第一步:解析解析网页 当我们依次点击下边的索引页面是,发现url的规律如下: 第1页:http://www. ...

  3. (79)【按键】[独立按键] - 1: 单击,双击,三击以及N击

    此按键程序的实现的功能是单个独立按键的[单击],[长按],[双击],[三击]以及[多击].本文分为三个部分, 第一个部分是说[单击],[长按]的程序: 第二部分是讲[双击]: 第三部分是讲[三击],[ ...

  4. java开发需掌握技能1

    1.熟练掌握Java基础.语法规范.集合框架等,基础语法.Java关键字.内部类.泛型.集合类使用场景2.Java io/nio框架体系.文本文件.二进制文件读写.nio.buffer机制3.Jsp. ...

  5. [BZOJ4237]稻草人:CDQ分治+单调栈

    分析 按\(y\)排序后CDQ分治,可以发现每个点可以影响的是\(x\)坐标的一段区间,可以使用扫描线+单调栈,在单调栈上二分即可解决,时间复杂度\(O(n \log^2 n)\). 通过归并排序可以 ...

  6. Java数据结构之排序---希尔排序

    希尔排序的基本介绍: 希尔排序同之前的插入排序一样,它也是一种插入排序,只不过它是简单插入排序之后的一个优化的排序算法,希尔排序也被称为缩小增量排序. 希尔排序的基本思想: 希尔排序是把数组中给定的元 ...

  7. [LeetCode]-algorithms-String to Integer (atoi)

    Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input cases. ...

  8. 微信小程序打印json log

    微信小程序中如果 res.data数据是一个json格式数据.console.log("===data===" + res.data);//如果这样打印出了是只会打印一个对象名称, ...

  9. react注

    创建新项目: npm create-react-app test1 运行项目:npm start

  10. jQuery.parseJSON()

    https://api.jquery.com/jQuery.parseJSON/ https://api.jquery.com/category/deprecated/deprecated-3.0/ ...