UVALIVE 5685 Difficult Routes [最短路问题变形,坑爹题]

UVALIVE 5685 Difficult Routes [最短路问题变形,坑爹题]

题目大意:
给你一个三维地图,里面N个点,给出对应的xyz坐标;给你M条边,连接对应编号的点。
每条边有两个值。
cost:两点的欧式距离。
d:两点的高度差(z轴差值的绝对值)除以两点在XY平面的投影的欧式距离,再乘以100,最后下取整,如果a点比b点高或者和b点持平,则d值为0。=>所以边有向。
给你一个起始点编号一个终点编号,再给你一个目标值d。
让你找一条最短路径(cost和最小),要求起点终点为对应的点,且这条路径上的最大d值为给定d值。起终点可能相同。

做法:
就是最短路嘛,特点是要求必须经过满足约束的边,那么就在松弛条件上面做手脚。
把dis数组开成两维的:dis[0][p]表示到该点还没满足条件时候的最短路,dis[1][p]表示到这点已经满足条件时候的最短路。
由于稀疏图,那么就开始spfa了。
从dis[0][s]=0开始,把其他所有值初始化置为-1或者inf。
松弛的时候这样,对于dis[0],该咋松弛就咋松弛。
对于邻接表中当前边的d值等于给定d值,那么就用当前点的min(dis[0][now],dis[1][now])去更新下一点的dis[1][p];
对于不等的情况,如果当前点的dis[1][now]不等于-1或者inf,那么就用dis[1][now]去更新dis[1][p]。
然后就完了。答案就是dis[1][t]。inf或者ans。

坑爹之处在于题目中N和M的数据范围少给了个0,RE到死哇。。一开始还tmd TLE。。。擦。。。

话说某些小盆友还用了spfa求最小环的想法,我觉得没必要的说。把满足条件后的点和不满足条件的点当成不同的点,那么根本就不存在环的问题了。。
对于起终点相同的情况,最短路径实际上的松弛方式就是i->j~k->i'。。。看嘛,哪里有环了。

附代码:
#include  < iostream >
#include 
< cstring >
#include 
< cstdio >
#include 
< cmath >
#include 
< queue >
using   namespace  std;
int  n,m,s,t,d;
#define  maxn 110005
#define  maxm 110005
const   double  eps  =  1e - 8 ;
int  sgn( double  x){ return  fabs(x)  <  eps  ?   0  : x  <   - eps  ?   - 1  :  1 ;}
struct  edge
{
    
int  p,next,d;
    
double  c;
    edge(){}
    edge(
int  a, int  b, int  _c, double  _d):p(a),next(b),d(_c),c(_d){}
}e[maxm];
int  tot;
struct  point
{
    
double  x,y,z;
    point(){}
    point(
double  a, double  b, double  c):x(a),y(b),z(c){}
    point 
operator   -  ( const  point p)
    {
        
return  point(x  -  p.x,y  -  p.y,z  -  p.z);
    }
    
double  norm()
    {
        
return  sqrt(x  *  x  +  y  *  y  +  z  *  z);
    }
    
double  norm2()
    {
        
return  sqrt(x  *  x  +  y  *  y);
    }
}p[maxn];
int  st[maxn];
void  init()
{
    tot 
=   0 ;
    fill(st,st 
+  n  +   1 , - 1 );
}
void  add( int  p, int  q, int  d, double  c)
{
    e[tot] 
=  edge(q,st[p],d,c);
    st[p] 
=  tot ++ ;
}
double  dis[ 2 ][maxn];
bool   in [maxn];
void  bfs()
{
    
for ( int  i  =   0 ;i  <   2 ;i ++ )    
        
for ( int  j  =   1 ;j  <=  n;j ++ )
            dis[i][j] 
=   - 1.0 ;
    fill(
in , in   +  n  +   1 , 0 );
    queue 
< int >  Q;
    Q.push(s);
    
in [s]  =   true ;
    dis[
0 ][s]  =   0.0 ;
    
while ( ! Q.empty())
    {
        
int  now  =  Q.front();
        Q.pop();
        
in [now]  =   false ;
        
for ( int  k  =  st[now]; ~ k;k  =  e[k].next)
        {
            
bool  mark  =   false ;
            
int  p  =  e[k].p;
            
int  dd  =  e[k].d;
            
double  cost  =  e[k].c;
            
if (dd  >  d)
                
continue ;
            
// cout << p << ' ' << dd << ' ' << cost << endl;
             if (sgn(dis[ 0 ][p] + 1 ==   0   ||  sgn(dis[ 0 ][p]  -  dis[ 0 ][now]  -  cost)  >   0 )
                dis[
0 ][p]  =  dis[ 0 ][now]  +  cost,mark  =   true ;
            
if (dd  ==  d)
            {
                
double  tmp ;
                
if (sgn(dis[ 1 ][now]  +   1.0 !=   0 )
                    tmp 
=  min(dis[ 0 ][now],dis[ 1 ][now]);
                
else
                    tmp 
=  dis[ 0 ][now];
                
if (sgn(dis[ 1 ][p]  +   1.0 ==   0   ||  sgn(dis[ 1 ][p]  -  tmp  -  cost)  >   0 )
                    dis[
1 ][p]  =  tmp  +  cost,mark = true ;
            }
            
else   if (sgn(dis[ 1 ][now] + 1 !=   0 )
            {
                
double  tmp  =  dis[ 1 ][now];
                
if (sgn(dis[ 1 ][p]  +   1.0 ==   0   ||  sgn(dis[ 1 ][p]  -  tmp  -  cost)  >   0 )
                    dis[
1 ][p]  =  tmp  +  cost,mark = true ;
            }
            
if (mark  &&   ! in [p])
            {
                Q.push(p);
                
in [p]  =   true ;
            }
            
// if(Q.size() > 100000)
            
//     cout << "fuck" << endl;
        }
    }
}
void  gao()
{
    
double  x,y,z;
    
for ( int  i  =   1 ;i  <=  n;i ++ )
    {
        scanf(
" %lf %lf %lf " , & x, & y, & z);
        p[i] 
=  point(x,y,z);
    }
    init();
    
for ( int  i  =   0 ;i  <  m;i ++ )
    {
        
int  a,b;
        scanf(
" %d %d " , & a, & b);
        
int  fuck  =  ( int )floor( 100   *  fabs((p[b].z  -  p[a].z))  /  (p[a]  -  p[b]).norm2());
        
double  l  =  (p[a]  -  p[b]).norm();
         if (sgn(p[a].z  -  p[b].z)  <   0 )
        {
            add(a,b,fuck,l);
            add(b,a,
0 ,l);
        }
        
else
        {
            add(b,a,fuck,l);
            add(a,b,
0 ,l);
        }
    }
    scanf(
" %d %d %d " , & s, & t, & d);
    bfs();
    
double  ans  =  dis[ 1 ][t];
    
// for(int i = 1;i <= n;i++)
    
//     printf("%.3lf %.3lf\n",dis[0][i],dis[1][i]);
     if (sgn(ans  +   1.0 ==   0 )
        puts(
" None " );
    
else
        printf(
" %.3lf\n " ,ans);
}
int  main()
{
    
while (scanf( " %d %d " , & n, & m)  ==   2   &&  (n  ||  m))
        gao();
}
Backspace

你可能感兴趣的:(UVALIVE 5685 Difficult Routes [最短路问题变形,坑爹题])