Dijkstra—链式向前星—快速幂
题目
链接:牛客283H-图论一顿套模版
解析
题目求的是乘积,但是又因为W一定是2的整数次幂。所以我们可以将乘法换为加法,2^x * 2^y = 2^(x+y)
只要我们求出x+y
的最小值,那么对应其答案也是最小值。算2^x
可以运用快速幂解决
所以总体上我们可以用dij+优先队列优化+链式向前星+快速幂解决
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
#include <cstdio> #include <cstring> #include <queue> #include <cmath> using namespace std; typedef long long ll; const int MOD = 1e9+7; const int MAXN = 1e5+10; const int INF = 0X3F3F3F3F; struct Edge //链式向前星存图 { int to, next; int val; };
struct Node //优先队列节点,pos表示顶点位置,cost表示从起点到该点需要的最优路径长度 { int pos, cost; Node(){} Node(int pos, int cost):pos(pos),cost(cost){} friend bool operator <(const Node & a, const Node & b) { return a.cost > b.cost; } };
int head[MAXN];
bool vis[MAXN]; int dis[MAXN]; Edge edge[MAXN]; int n, m, s, t;
int mod_pow(int x, int n) { int ans = 1; while(n) { if(n & 1) ans = ans*x%MOD; x = x*x%MOD; n >>= 1; } return ans; }
void addEdge(int e1, int e2, int id, int val) { edge[id].to = e2; edge[id].next = head[e1]; head[e1] = id; edge[id].val = val; }
void Dijkstra() { priority_queue<Node> q; Node p; dis[s] = 0; q.push(Node(s, 0)); Edge e; while(!q.empty()) { p = q.top(); q.pop(); if(vis[p.pos]) continue; vis[p.pos] = true; for(int k = head[p.pos]; k != -1; k = edge[k].next) { e = edge[k]; if(dis[e.to] > dis[p.pos] + e.val) { dis[e.to] = dis[p.pos] + e.val; q.push(Node(e.to, dis[e.to])); } } } } int main() { scanf("%d%d%d%d", &n, &m, &s, &t); memset(head, -1, sizeof(head)); memset(vis, false, sizeof(vis)); for(int i = 1; i <= n; i++) dis[i] = INF; int e1, e2, val; for(int i = 1; i <= m; i++) { scanf("%d%d%d", &e1, &e2, &val); addEdge(e1, e2, i,log2(val)); } Dijkstra(); if(dis[t] == INF) printf("-1\n"); else printf("%d\n",mod_pow(2,dis[t])); return 0; }
|