第一思路是想用搜索来做,直接DFS所有可能的情况,然后找到最小的即可,不过不能满足该题的时间复杂度
#include<bits/stdc++.h> using namespace std; const int MAX=2010,inf=0x3f3f3f3f; double MIN=99999; int mapp[MAX][MAX]; int n,m,a,b; bool visited[MAX]; stack<int>stk;//存储路径 void dfs(int index){ if(index==b){ double money=100; vector<int>temp; while(!stk.empty()){ temp.push_back(stk.top()); stk.pop();//回溯 } for(int i=0;i<temp.size();i++){ money/=(1-temp[i]*1.0/100);//计算 } if(money<MIN){ MIN=money; } for(int i=temp.size()-1;i>=0;i--){ stk.push(temp[i]); } } else{ for(int i=1;i<=n;i++){ if(visited[i]||mapp[index][i]==inf){ continue; } visited[i]=true; stk.push(mapp[index][i]); dfs(i); visited[i]=false; stk.pop(); } } } int main(){ memset(visited,false,sizeof(visited)); cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ mapp[i][j]=inf; } } for(int i=0;i<m;i++){ int u,v,w; cin>>u>>v>>w; mapp[u][v]=mapp[v][u]=w; } cin>>a>>b; visited[a]=true; dfs(a); cout<<fixed<<setprecision(8)<<MIN<<endl; return 0; }
第二思路是使用dijkstra
首先需要清楚的是我们的建图,正常计算的话应该是沿着路径用100进行计算,例如走1->2->3的话,我们是(100/(1-2/100))/(1-1/100)=103.07153164
因此我们定义每一条边的权值为1-百分比
这样我们可以确定最后的答案是100/路径乘积
所以找到一条最大路径即可,即最短路径的反面
#include<bits/stdc++.h> using namespace std; #define pii pair<double,int> //注意都要使用double const int MAX=2010*2,inf=0x3f3f3f3f; double mapp[MAX][MAX]; int n,m,a,b; bool visited[MAX]; double dis[MAX]; void dijkstra(){ memset(visited,false,sizeof(visited)); for(int i=1;i<=n;i++){ dis[i]=0; } dis[a]=1; priority_queue<pii,vector<pii>,less<pii> >p;//大根堆 p.push({1,a}); while(!p.empty()){ int u=p.top().second; p.pop(); if(visited[u]){ continue; } visited[u]=true; for(int i=1;i<=n;i++){ if(!visited[i]&&mapp[u][i]!=inf){ if(dis[i]<dis[u]*mapp[u][i]){ dis[i]=dis[u]*mapp[u][i]; p.push({dis[i],i}); } } } } } int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ mapp[i][j]=inf; } } for(int i=0;i<m;i++){ int u,v,w; cin>>u>>v>>w; mapp[u][v]=mapp[v][u]=1-w*1.0/100; } cin>>a>>b; dijkstra(); cout<<fixed<<setprecision(8)<<100/dis[b]<<endl; return 0; }