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();
}

posted on 2011-10-29 01:01 BUPT-[aswmtjdsj] @ Penalty 阅读(550) 评论(0)  编辑 收藏 引用 所属分类: 图论UVAlive Solution Report


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年8月>
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910

导航

统计

常用链接

留言簿(1)

随笔分类(150)

随笔档案(71)

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜