水题。。可是做的人很少。。。
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">思路: 把每个点i拆成两个点i和i+n,所有与i相关的出边与i相连,与i相关的入边与i+n相连,在求s到t的最短路时就是求s到t+n的最短路,这样就能解决环的问题了。然后看一个二维的dis[i][j],代表从s到i困难度最高为j的最短路,最后上Dijkstra,1A~</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="cpp">#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<cstdlib>
using namespace std;
const int maxn = 50005;
const int maxd = 25;
const double inf = 1e12;
struct Node{
int a,b,dis;
Node(int a,int b,int dis): a(a),b(b),dis(dis) {}
bool operator < (const Node &z) const {
return dis > z.dis;
}
};
struct Point{
double x,y,z;
}p[maxn];
struct Edge{
int to,d;
double cost;
};
int n,m,s,t,lv;
double dis[maxn][maxd];
vector<Edge> G[maxn];
priority_queue<Node> que;
void init(){
while(!que.empty()) que.pop();
for(int i=0;i<n;i++) G[i].clear();
}
int cal_d(int a,int b){
if(p[a].z < p[b].z){
double rise = p[b].z - p[a].z;
double run = sqrt((p[a].x - p[b].x)*(p[a].x - p[b].x) + (p[a].y - p[b].y)*(p[a].y - p[b].y));
return (int)(100*rise/run);
}else return 0;
}
double cal_cost(int a,int b){
return sqrt((p[a].x - p[b].x)*(p[a].x - p[b].x) + (p[a].y - p[b].y)*(p[a].y - p[b].y) + (p[a].z - p[b].z)*(p[a].z - p[b].z));
}
void add_Edge(int from,int to){
Edge e;
e.to = to + n;e.d = cal_d(from,to);e.cost = cal_cost(from,to);
G[from].push_back(e);
e.to = from + n;e.d = cal_d(to,from);;
G[to].push_back(e);
}
void dij(){
for(int i=0;i<2*n;i++){
for(int j=0;j<=lv;j++){
dis[i][j] = inf;
}
}
dis[s][0] = 0;
que.push(Node(s,0,0));
while(!que.empty()){
Node nd = que.top();que.pop();
int v = nd.a,d = nd.b;
if(dis[v][d] < nd.dis) continue;
int u = v % n;
for(int i=0;i<G[u].size();i++){
Edge e = G[u][i];
int k = max(d,e.d);
if(k <= lv && dis[e.to][k] > dis[v][d] + e.cost){
dis[e.to][k] = dis[v][d] + e.cost;
que.push(Node(e.to,k,dis[e.to][k]));
}
}
}
if(dis[t+n][lv] == inf) printf("None\n");
else printf("%.1f\n",dis[t+n][lv]);
}
int main(){
while(~scanf("%d%d",&n,&m)){
if(n + m == 0) break;
init();
for(int i=0;i<n;i++){
scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
}
int a,b;
while(m--){
scanf("%d%d",&a,&b);
a--;b--;
add_Edge(a,b);
}
scanf("%d%d%d",&s,&t,&lv);
s--;t--;
dij();
}
return 0;
}