回顾很久之前做的题目,机考说不定真考图论了呢,关键是shortest path后的单向梯度下降算法,注意这里是与结点n之间的距离,不是0
- step[i]+=path(t.v,j); 这个包含了动态规划的思想,从源节点的所有路径数,归结为找寻子源节点到n的总路径数
- 注意题目对路径数的规模限制: 返回对
10^9+7
取余 的结果
long long INF=pow(10,10);
int N=4*pow(10,4); //最大的结点数
//The line is special for the line that has weight
struct Edge{
int v,w;
Edge(int v,int w):v(v),w(w){}
};
struct Node{
int u,w;//w is set special for the capital point: means the final weight
Node(){}
Node(int u,int w):u(u),w(w){} //初始的w都是没有值的
bool operator<(const Node &a) const
{
return w>a.w;
}
};
class Solution {
public:
priority_queue<Node>q; //Why using this? To maintain the Node that added to the V-U is the smallest!
vector<vector<Edge>>g;//altered Adjacency List
vector<bool> vis;
vector<long long> dist; //未加入连通图的结点dist值都是无穷大
int p; //记录路径的总数
int countRestrictedPaths(int n, vector<vector<int>>& edges) {
auto dijkstra=[this](int s){
//......initialize
dist[s]=0;
q.push(Node(s,0)); //第一个结点入队列
while(!q.empty()){
Node e=q.top();
q.pop();
int u=e.u;
if(!vis[u]){ //1.访问过都不再访问1
vis[u]=true;
int num=g[u].size();
for(int i=0;i<num;i++){
int v=g[u][i].v;//u point's NO.i Adjacency point
int c=g[u][i].w;
//Sift1
if(vis[v]) //2.访问都不再访问2
continue;
//Sift2: choose to update the dist martrix or not
//下面是核心代码部分:
if(dist[v]>dist[u]+c){
dist[v]=dist[u]+c;
q.push(Node(v,dist[v])); //注意: w是从这里产生值的
}
}
}
}
};
p=0;
g.resize(N);
dist.resize(n+1);
fill(dist.begin(),dist.end(),INF);
vis.resize(n+1);
fill(vis.begin(),vis.end(),false);
for(auto &t:edges){
g[t[0]].push_back(Edge(t[1],t[2]));
g[t[1]].push_back(Edge(t[0],t[2]));
}
dijkstra(n); //下标从1开始
vector<int> step(n+1,-1);
function<int(int,int)> path=[&](int i,int j)->int{ //注意这里的返回值为路径总数
if(i==j){
return 1;
}
if(step[i]!=-1) return step[i]; //说明前面肯定求过了
step[i]=0; //遍历到当前结点,就要初始化为0
for(auto &t:g[i]){
if(dist[i]<=dist[t.v]) //因为下坡具有单向性,所以不会回溯
continue;
step[i]+=path(t.v,j);
if(step[i]>(int)(pow(10,9)+7))
step[i]=step[i]%(int)(pow(10,9)+7);
}
return step[i];
};
return path(1,n);
}
};