SCUT - 486 - 无向图上的点 - Dijkstra
好像原题是这个?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的更多相关文章
- 图上最短路(Dijkstra, spfa)
单源最短路径 题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包含三个整数N.M.S,分别表示点的个数.有向边的个数.出发点的编号. 接下来 ...
- SCUT - 483 - 数轴上的点
https://scut.online/p/483 改了题目之后发现,其实n个点放在[1,2N],要求间距至少是2,那么有且只有一个点和前面点的间距是3(设-1存在一个点),其他点的间距都必须是2.排 ...
- SCUT - 484 - 平面上的点 - 数据结构
https://scut.online/p/484 一开始想的是按固定斜率的直线从无穷扫下来,但是一直都WA,不知道是哪里错了还是精度问题? #include<bits/stdc++.h> ...
- 关于scut在unity上的主动推送
自带的samples里面,chat的例子涉及主动推送,可作为参考. 在unity里面接收主动推送用Net.CommonCallback 服务端最近的新版本更改了接口,有两种方法推送: ActionFa ...
- 在加权无向图上求出一条从1号结点到N号结点的路径,使路径上第K+1大的边权尽量小
二分+最短路算法 #include<cstdio> #include<iostream> #include<cstring> #include<algorit ...
- UVa 10801 - Lift Hopping(dijkstra最短路)
根据题意,以每一层楼为顶点,每个电梯可以到达的两层楼之间的秒数为每一条边的权值,以此构建一个无向图.然后利用dijkstra求出最短的时间,注意每次换乘电梯需要等待60s(因为同一个电梯上的楼层是相互 ...
- 最短路径算法——Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson
根据DSqiu的blog整理出来 :http://dsqiu.iteye.com/blog/1689163 PS:模板是自己写的,如有错误欢迎指出~ 本文内容框架: §1 Dijkstra算法 §2 ...
- hdu 1874 Dijkstra算法
先贴个网上找的比较通俗易懂的教程: 2.1Dijkstra算法(非负权,使用于有向图和无向图) Dijkstra算法是典型最短路算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心 ...
- UVA5135 Mining Your Own Business ( 无向图双连通分量)
题目链接 题意:n条隧道由一些点连接而成,其中每条隧道链接两个连接点.任意两个连接点之间最多只有一条隧道.任务就是在这些连接点中,安装尽量少的太平井和逃生装置,使得不管哪个连接点倒塌,工人都能从其他太 ...
随机推荐
- 6. ClustrixDB 备份恢复
ClustrixDB备份恢复: 一.传统MySQL的备份/恢复 shell> mysqldump -u user -h clustrix host --single-transaction ...
- [BZOJ3796]Mushroom追妹纸:后缀自动机+KMP
分析 这道题有个\(O(n)\)的后缀自动机做法,感觉很好理解就在这说一下. 先对\(s1\)和\(s2\)求最长公共子串,对于\(s2\)的每一个下标\(i\),求一个\(f[i]\)表示以\(s2 ...
- Spring Boot教程(三)消费Restful的web服务
构架工程 创建一个springboot工程,去消费RESTFUL的服务.这个服务是 http:///gturnquist-quoters.cfapps.io/api/random ,它会随机返回Jso ...
- pycharm 安装激活
下载pycharm :http://www.jetbrains.com/pycharm/download/download 安装 直到 finish 下载补丁jetbrains-agent.jar并添 ...
- ppt制作的相关技巧
一.好的ppt需要达到的目标是: 用情感打动你,用逻辑说服你 二.好主题,写在封面上 主标题带来冲击力,副标题提供描述性细节 如何打造好标题: (1)用数字给标题添彩 (2)想畅销书学标题 (3)向流 ...
- 四、IDEA创建SpringBoot项目
1.从官网下载之后直接导入IDEA: 下载完成解压之后如下图: IDEA导入该项目: 之后一路next即可 导入成功之后你可能会发现左下角一直有个进度条在进行,傻傻的同学可能以为是在下载jar包,下个 ...
- 各种tips汇总
才疏学浅,以下整理的东西有些可能还不成熟,措辞有待改进,但是都是我在敲代码的过程中,一点一滴积累总结的,如有不妥和错误,希望大家指正. 让行及元素变成块级元素的方式: position:absolut ...
- 分布式消息队列 Celery 的最佳实践
目录 目录 不使用数据库作为 Broker 不要过分关注任务结果 实现优先级任务 应用 Worker 并发池的动态扩展 应用任务预取数 保持任务的幂等性 应用任务超时限制 善用任务工作流 合理应用 a ...
- Python Module_openpyxl_styles 样式处理
目录 目录 前言 系统软件 Working with styles Styles can be applied to the following aspects Styles模块 Copying st ...
- node初始化配置no
原文链接:https://blog.csdn.net/jianleking/article/details/79130667 引言: 很久没有在windows上配过node, 记得以前node环境变量 ...