题干:
由于临近广西大学建校90周年校庆,西大开始了喜闻乐见的校园修缮工程!
然后问题出现了,西大内部有许许多多的道路,据统计有N栋楼和M条道路(单向),每条路都有“不整洁度”W,现在校方想知道从S楼到T楼的所有路径中,“不整洁度”乘积最小是多少。
由于答案可能很大,所以你需要将最后的答案对109+7取模。
输入描述:
第一行为四个整数N、M、S、T,意义如上。
第2至第M+1行每行表示一条道路,有三个整数,分别表示每条道路的起点u,终点v和“不整洁度”W。
输入保证没有自环,可能有重边。
其中W一定是2的整数次幂。
输出描述:
输出一个整数,表示最小的不整洁度之乘积对109+7取模的结果。
若无解请输出 -1
示例1
输入
复制
4 4 1 3 1 2 8 1 3 65536 2 4 2 4 3 16
输出
复制
256
解题报告:
把乘法转化成加法就可以跑Dijkstra了。。
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 2e5 + 5;
struct Edge {int to;int ne;ll w;
} e[MAX];
struct Point {int o;ll c;Point(){}Point(int o,ll c):o(o),c(c){}friend bool operator <(const Point & a,const Point & b) {return a.c > b.c;}
};
const ll INF = 0x3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
int n,m,s,t;
int tot;
int head[MAX];
ll dis[MAX];
bool vis[MAX];
void add(int x,int y,ll w) {e[++tot].to = y;e[tot].w = w;e[tot].ne = head[x];head[x] = tot;
}
ll qpow(ll a,ll k) {ll res = 1;while(k) {if(k&1) res = (res * a) % mod;k>>=1;a = (a*a)%mod;}return res % mod;
}
void Dijkstra() {for(int i = 1; i<=n; i++) dis[i] = INF;memset(vis,0,sizeof vis);dis[s] = 0;priority_queue<Point> pq;pq.push(Point(s,0));while(!pq.empty()) {Point cur = pq.top();pq.pop(); if(vis[cur.o]) continue;vis[cur.o]=1;for(int i = head[cur.o]; i!=-1; i=e[i].ne) {//if(vis[cur.o]) continue;if(e[i].w + dis[cur.o] < dis[e[i].to]) {dis[e[i].to] = e[i].w + dis[cur.o];pq.push(Point(e[i].to,dis[e[i].to]));}}}}int main()
{ll c;memset(head,-1,sizeof head);cin>>n>>m>>s>>t;for(int i = 1,a,b; i<=m; i++) {scanf("%d%d%lld",&a,&b,&c);ll tmp = (ll)log2(c);add(a,b,tmp);}Dijkstra();if(dis[t] == INF) puts("-1");else printf("%lld\n",qpow(2,dis[t]%mod));return 0 ;}