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条隧道由一些点连接而成,其中每条隧道链接两个连接点.任意两个连接点之间最多只有一条隧道.任务就是在这些连接点中,安装尽量少的太平井和逃生装置,使得不管哪个连接点倒塌,工人都能从其他太 ...
随机推荐
- 集合比较器报错java.lang.IllegalArgumentException: Comparison method violates its general contract!
Collections.sort(listMonthlyUsage, new Comparator<MonthlyUsageDto>() { //按照元素从小到大排序 @Override ...
- 实战build-react(二)-------引入Ant Design
安装 Ant Design npm install antd --save 或 yarn add antd 注释:https://www.jianshu.com/p/21caf40ee93e(cop ...
- Java中使用Scanner类进行键盘的输入详解
我们在使用Java写代码时,经常会遇到从键盘输入字符串等操作,这时候我们需要用到的是我们的Scanner类来实现获取用户从键盘上的输入操作. Scanner类是一个基于正则表达式的文本扫描器,它可以从 ...
- 使用 UIStoryBoard 语法糖
最后更新: 2018-09-06 当你用 UIStoryBoard (以下简称 'SB') 做iOS开发时候,总是避免不了设置 StoryBoard ID 的问题, StoryBoard ID 是一个 ...
- 【错误记录】Python 负数取余问题
print(-123%10) # 输出 7 print(-123%-10) # 输出 -3 这里面第二条是我们一般意义上的取余操作.这里也特别标注一下,如果涉及到负数取余要用上述解决办法. ...
- JavaScript DOM位置尺寸API
我们需要了解几个基础概念,每个HTML元素都有下列属性 offsetWidth clientWidth scrollWidth offsetHeight clientHeight scrollHeig ...
- ScvQ的技术栈
前端:spring mybatis hibernate struts2 SpringMVC echache quartz 后台:servlet jsp jdbc io html css javascr ...
- 【洛谷T89379 【qbxt】复读警告】
题目链接 这个题可以应用dp #include<bits/stdc++.h> using namespace std; ; inline int read() { ,b=; char c= ...
- 一元回归1_基础(python代码实现)
python机器学习-乳腺癌细胞挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003&u ...
- 四十、python中的生成器和迭代器
A.生成器(包含yield的就是生成器) def func(): print(11) yield 1 print(22) yield 2 print(33) yield 3 print(44) yie ...