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条隧道由一些点连接而成,其中每条隧道链接两个连接点.任意两个连接点之间最多只有一条隧道.任务就是在这些连接点中,安装尽量少的太平井和逃生装置,使得不管哪个连接点倒塌,工人都能从其他太 ...
随机推荐
- vue学习-day03(动画,组件)
目录: 1.品牌列表-从数据库获取列表 2.品牌列表-完成添加功能 3.品牌列表-完成删除功能 4.品牌列表-全局配置数据接口的根域名 5.品牌列表-全局配置emulateJS ...
- Codeforces Round #287 (Div. 2) E. Breaking Good 路径记录!!!+最短路+堆优化
E. Breaking Good time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- 2019 Multi-University Training Contest 3 T6 - Fansblog
Fansblog Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ...
- 【BZOJ4195】 [Noi2015]程序自动分析
Description 在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足. 考虑一个约束满足问题的简化版本:假设x1,x2,x3,…代表程序中出现的变量,给定n个形如xi=xj或x ...
- event.stopPropagation()和event.preventDefault(),return false的区别
我写公司的官网遇到一个问题,轮播图的上一层有一块内容,用鼠标拖动那块内容的时候下一层的轮播图也会跟着拖动,而上面的那层的内容是不会动的,我想这就是冒泡事件在作祟了吧 跟冒泡事件相关的,我想到三个: 1 ...
- Spring Cloud Stream教程(四)消费群体
虽然发布订阅模型可以轻松地通过共享主题连接应用程序,但通过创建给定应用程序的多个实例来扩展的能力同样重要.当这样做时,应用程序的不同实例被放置在竞争的消费者关系中,其中只有一个实例预期处理给定消息. ...
- EF 视图查询坑
EF 视图在查询的时候如果主键一样则默认的数据都是第一条查询的数据
- ES6 字符串的解构赋值
字符串也可以解构赋值.这是因为此时,字符串被转换成了一个类似数组的对象. const [a, b, c, d, e] = 'hello'; a // "h" b // " ...
- C#调用本地摄像头-AForge库简单使用
介绍 AForge百度词条: https://baike.baidu.com/item/AForge.NET/114415?fr=aladdin 用途 调用笔记本电脑自带的相机 示例 源码 using ...
- kafka-manager怎么查看topic里的数据量
https://jingyan.baidu.com/article/eb9f7b6d367679869364e8d4.html