题目描述
牛牛为了向牛妹表达爱意,决定亲自给牛妹送上礼物。牛牛住在城市s,而牛妹住在城市t(牛牛和牛妹并不在同一座城市)。牛客国一共有n座城市,这n城市之间有m条城际高速可以让连接的城市相互通行。在牛客国,人们喜欢用组合数C_a^b来计数,所以通过某一条城际高速所需要的过路费也是用C_a^b来表示的。并且牛客国比起加法,更偏爱乘法,所以从城市s到达城市t所需要的总花费为路径上经历过的城际高速过路费之积,即∏i∈s→tC_{a_i}^{b_i}。牛牛了省钱想让你帮助他规划一条花费最少的路线,并把总花费告诉牛牛。由于答案可能很大请对10^9+7取模。
示例1
输入
5,5,1,5,[[1,2,1,1],[1,5,5,3],[3,5,1,1],[2,4,1,1],[4,5,2,1]]
返回值
2
说明
1->2->4->5距离最短,为C11∗C11∗C21=1∗1∗2=2C_1^1*C_1^1*C_2^1=1*1*2=2C11∗C11∗C21=1∗1∗2=2
备注:
m条城际高速的格式为 u,v,a,b,表示城市u和城市v之间有城际高速,通过该城际高速所需要的过路费为C_a^b。数据保证s和t之间有通路。
1≤n≤500,1≤m≤n∗(n−1)/2,1≤b≤a≤1000,1≤s,t≤n,1≤u,v≤n,s!=t。
思路:最短路模板题,只是走过的路径不能直接用乘积计数,因为一定会爆long long的,我们考虑乘法和对数的转换,因为乘积越大,其对数肯定也越大。
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param n int整型 有n个城市
* @param m int整型 有m条路径
* @param s int整型 起始城市坐标
* @param t int整型 终点城市坐标
* @param edge int整型二维数组 边的格式如下:[[u1,v1,a1,b1],[u2,v2,a2,b2],...]
* @return int整型
*/
class node{
int v;
double w1;
long w2;
public node(int v,double w1,long w2){
this.v=v;
this.w1=w1;
this.w2=w2;
}
}
private boolean[] vis;
private double[] dis1;
private long[] dis2;
private int mod=1000000007;
private List<List<node>> edges;
public int minDist (int n, int m, int s, int t, int[][] edge) {
// write code here
vis=new boolean[n+1];
dis1=new double[n+1];
dis2=new long[n+1];
edges=new ArrayList<>();
long[][] c2=new long[1005][1005];
double[][] c1=new double[1005][1005];
for(int i=0;i<=1000;i++)
c1[i][0]=c2[i][0]=1;
for(int i=1;i<=1000;i++)
for(int j=1;j<=i;j++){
c1[i][j]=c1[i-1][j]+c1[i-1][j-1];
c2[i][j]=(c2[i-1][j]+c2[i-1][j-1])%mod;
}
for(int i=1;i<=1000;i++)
for(int j=1;j<=i;j++)
c1[i][j]=Math.log(c1[i][j]);
for(int i=0;i<=n;i++)
edges.add(new ArrayList<>());
for(int[] e : edge){
int u=e[0],v=e[1],a=e[2],b=e[3];
edges.get(u).add(new node(v,c1[a][b],c2[a][b]));
edges.get(v).add(new node(u,c1[a][b],c2[a][b]));
}
for(int i=1;i<=n;i++){
dis2[i]=1;
dis1[i]=1e9;
}
dj(s);
return (int)dis2[t];
}
private void dj(int start){
Queue<Integer> q=new LinkedList<>();
q.add(start);
dis1[start]=0;
vis[start]=true;
while(!q.isEmpty()){
int now=q.poll();
vis[now]=false;
for(node nxt : edges.get(now)){
if(dis1[nxt.v]>dis1[now]+nxt.w1){
dis1[nxt.v]=dis1[now]+nxt.w1;
dis2[nxt.v]=dis2[now]*nxt.w2%mod;
if(!vis[nxt.v]){
q.add(nxt.v);
vis[nxt.v]=true;
}
}
}
}
}
}