2019安徽省程序设计竞赛 D.自驾游(最短路)

这道题最后没过,估计是痛失省一了,现在来补一下,当时思路是对的应该是代码出了问题导致样例没过最后nc的除了2,一直WA

题意:

给一张联通图,有两个导航系统,其中一个系统认为第i条边的权值是Pi,另一个系统认为是Qi(给定Pi和Qi),然后每个导航系统对于每条边i有个判定

其中一个是hero(vi)+Pi>hero(ui)会报警一次,另一个系统是a(vi)+Qi>a(ui)会报警一次,ui是边i的一个结点vi是另一个结点,让求一条两个系统警告次数相加最少的一条路径。

思路:

先从终点n作为起点跑两次最短路,一个按Pi为权值,求出每个节点v的hero(v),第二次以Qi为权值,求出每个节点v的a(v)。

然后遍历每条边,用警告次数作为权值从1作为起点再跑一次最短路求出结果即可。最短路的求法我用了Dij+堆优化。

这个改正过的代码只过了样例,没法实际测试了,有不对的地方还请大佬指正。

样例数据:

Sample input

5 7
3 4 7 1
1 3 2 20
1 4 17 18
4 5 25 3
1 2 10 1
3 5 4 14
2 4 6 5

Sample output

1

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e4 + 5;
const int maxm = 5e4 + 5;
const int inf = 0x3f3f3f3f;
struct edge{
    int to, wp, wq, ww, next;
} ed[maxm*2];
int n, m, head[maxn], tot;
int hero[maxn], a[maxn], dis[maxn];
bool vis[maxn];
inline void add( int u, int v, int p, int q ){
    ed[tot].to = v;
    ed[tot].wp = p;
    ed[tot].wq = q;
    ed[tot].ww = 0;
    ed[tot].next = head[u];
    head[u] = tot ++;
}

inline void dij1(int s){
    memset( vis, 0, sizeof(vis) );
    memset( hero, inf, sizeof(hero) );
    priority_queue< pair<int, int> > q;
    vis[s] = 1;
    hero[s] = 0;
    q.push( make_pair( 0, s ) );
    while( !q.empty() ){
        int u = q.top().second;
        q.pop();
        for( int i=head[u]; i!=-1; i=ed[i].next ){
            int v = ed[i].to;
            if( hero[v]>hero[u]+ed[i].wp ){
                hero[v] = hero[u]+ed[i].wp;
                if( !vis[v] ){
                    vis[v] = 1;
                    q.push( make_pair( -hero[v], v ) );
                }
            }
        }
    }
}

inline void dij2(int s){
    memset( vis, 0, sizeof(vis) );
    memset( a, inf, sizeof(a) );
    priority_queue< pair<int, int> > q;
    vis[s] = 1;
    a[s] = 0;
    q.push( make_pair( 0, s ) );
    while( !q.empty() ){
        int u = q.top().second;
        q.pop();
        for( int i=head[u]; i!=-1; i=ed[i].next ){
            int v = ed[i].to;
            if( a[v]>a[u]+ed[i].wq ){
                a[v] = a[u]+ed[i].wq;
                if( !vis[v] ){
                    vis[v] = 1;
                    q.push( make_pair(-a[v], v) );
                }
            }
        }
    }
}

inline void dij3( int s ){
    memset( vis, 0, sizeof(vis) );
    memset( dis, inf, sizeof(dis) );
    priority_queue< pair<int, int> > q;
    vis[s] = 1;
    dis[s] = 0;
    q.push( make_pair( 0, s ) );
    while( !q.empty() ){
        int u = q.top().second;
        q.pop();
        for( int i=head[u]; i!=-1; i=ed[i].next ){
            int v = ed[i].to;
            if( dis[v]>dis[u]+ed[i].ww ){
                dis[v] = dis[u]+ed[i].ww;
                if( !vis[v] ){
                    vis[v] = 1;
                    q.push( make_pair( -dis[v], v ) );
                }
            }
        }
    }
}

inline void bfs(int s){
    queue<int> q;
    memset( vis, 0, sizeof(vis) );
    vis[s] = 1;
    q.push(s);
    while( !q.empty() ){
        int u = q.front();
        q.pop();
        for( int i=head[u]; i!=-1; i=ed[i].next ){
            int v = ed[i].to;
            if( !vis[v] ){
                vis[v] = 1;
                if( hero[v]+ed[i].wp>hero[u] ) ed[i].ww ++;
                if( a[v]+ed[i].wq>a[u] ) ed[i].ww ++;
            }
        }
    }
}

int main(){
    // freopen("in.txt", "r", stdin);
    tot = 0;
    memset( head, -1, sizeof(head) );
    scanf("%d%d", &n, &m);
    for( int i=0; i<m; i++ ){
        int u, v, p, q;
        scanf("%d%d%d%d", &u, &v, &p, &q);
        add( u, v, p, q );
        add( v, u, p, q );
    }
    dij1(n);
    dij2(n);
    //注释掉的就是当时写的错误遍历边的代码
    // for( int i=1; i<=n; i++ ){
    //     for( int j=head[i]; j!=-1; j=ed[j].next ){
    //         if( ed[j].wp+hero[ed[j].to]>hero[i] ) ed[j].ww ++;
    //         if( ed[j].wq+a[ed[j].to]>a[i] ) ed[j].ww ++;
    //     }
    // }
    bfs(1);        //应该从1开始向外bfs遍历边,即可找出正确答案
    dij3(1);
    printf("%d\n", dis[n]);

    return 0;
}

 

转载于:https://www.cnblogs.com/WAautomaton/p/10912206.html

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
安卓自驾游APP的开发是为了提供给用户一个方便实用的工具,帮助他们在自驾游过程中获得相关的信息和服务。这个APP可以包含以下功能: 1. 地图导航:该功能可以提供准确的自驾路线导航,包括起点、途径点和目的地,还可以显示实时交通信息以避开拥堵区域。 2. 景点推荐:这个功能可以向用户推荐自驾游线路上的风景名胜点、旅游景点、购物中心等。用户可以根据自己的偏好进行选择,并了解每个景点的介绍、评价和开放时间。 3. 餐饮推荐:用户可以在APP上查找到自驾路线上的各类餐馆、咖啡店和酒吧等,选择适合自己口味和需求的餐饮场所,并查看用户评价和菜单信息。 4. 车辆服务:这个功能可以提供附近的加油站、洗车店和维修点等,方便用户在自驾过程中维护车辆并满足相关需求。 5. 实时天气:用户可以通过APP查看目的地和途径地区的实时天气情况,以便合理安排自己的行程和装备。 为了实现这些功能,安卓自驾游APP的开发需要有以下几个步骤: 1. 需求分析:根据目标用户的需求,确定APP需要提供的功能模块,并设计相应的用户界面和交互流程。 2. 数据采集和整合:收集地图、景点、餐饮等相关数据,并通过API或其他方式进行整合和存储,以供用户使用。 3. 界面设计和开发:根据需求分析的结果,设计用户界面的布局、交互方式和视觉风格,并进行开发和编码。 4. 功能实现:根据需求实现各个功能模块,包括地图导航、景点推荐、餐饮推荐等,并确保它们能够正常运行和交互。 5. 测试和优化:对开发好的APP进行全面的测试,修复bug,并进行性能优化,以提高用户体验。 6. 上线和推广:将开发好的APP上线到安卓应用商店,并通过推广手段宣传推广,吸引更多用户下载和使用。 总的来说,安卓自驾游APP的开发需要考虑用户需求、数据整合、界面设计、功能实现等多个因素,以提供给用户一个方便实用、信息丰富的自驾游工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值