E-免费的飞机

题目链接:https://ac.nowcoder.com/acm/contest/699/E

题目意思:有n个飞机场,给你起点s,终点e,有m种带权的无向边飞机线路。有k个线路,可以从中选一个免费飞行。问是否使用免费飞机票,并输出最短路花费。

思路:

1.先建普通飞机线路,算出最短路。再每一条免费线路重新算一次最短路,再判断是否比之前小。

spfa写法:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
struct node{
    int u,v,w,next;
}e[2050];
int head[1050],vis[1050],d[1050];
int st,ed,n,m,k,cnt;
int from[1050],to[1050],val[1050];
void add(int u,int v,int w)
{
    e[cnt].u=u;
    e[cnt].v=v;
    e[cnt].w=w;
    e[cnt].next=head[u];
    head[u]=cnt++;
}

void spfa()//spfa算最短路
{
    memset(d,0x3f,sizeof(d));
    memset(vis,0,sizeof(vis));
    queue<int> q;
    vis[st]=1;
    d[st]=0;
    q.push(st);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].v;
            if(d[v]>d[u]+e[i].w)
            {
                d[v]=d[u]+e[i].w;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
}

int main()
{
    int u,v,w;
    cnt=0;
    memset(head,-1,sizeof(head));
    std::ios::sync_with_stdio(false);
    cin>>n>>st>>ed>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>from[i]>>to[i]>>val[i];
        add(from[i],to[i],val[i]);
        add(to[i],from[i],val[i]);
    }
    spfa();
    int ans=d[ed];//记录没有用免费机票的最短路
    int anss=inf;
    cin>>k;
    for(int i=0;i<k;i++)
    {
        cin>>u>>v;
        add(u,v,0);
        add(v,u,0);
        spfa();//每条免费线路算一次最短路
        anss=min(anss,d[ed]);
        cnt=0;
        memset(head,-1,sizeof(head));//记得初始化
        for(int i=1;i<=m;i++)
        {
            add(from[i],to[i],val[i]);
            add(to[i],from[i],val[i]);
        }
    }
    if(ans==anss)
        cout<<"No"<<endl<<ans<<endl;
    else
        cout<<"Yes"<<endl<<anss<<endl;
    return 0;
}

dijkstra写法:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define inf 0x3f3f3f3f
#include<queue>
using namespace std;
typedef long long ll;
struct node{
    int u,v,w,next;
}e[2050];
struct nd{
    int id;
    int dis;
    bool operator <(const nd &a)const{
        return a.dis<dis;
    }
};
int head[1050],vis[1050],d[1050];
int st,ed,n,m,k,cnt;
int from[1050],to[1050],val[1050];
void add(int u,int v,int w)
{
    e[cnt].u=u;
    e[cnt].v=v;
    e[cnt].w=w;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
void dij()//优先队列优化
{
    priority_queue<nd> q;
    memset(d,0x3f,sizeof(d));
    memset(vis,0,sizeof(vis));
    d[st]=0;
    while(!q.empty())
        q.pop();
    q.push({st,0});
    while(!q.empty())
    {
        nd t=q.top();
        q.pop();
        int u=t.id;
        if(vis[u])
            continue;
        vis[u]=1;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].v;
            if(!vis[v]&&d[v]>d[u]+e[i].w)
            {
                d[v]=d[u]+e[i].w;
                q.push({v,d[v]});
            }
        }
    }
}

int main()
{
    int u,v,w;
    cnt=0;
    memset(head,-1,sizeof(head));
    std::ios::sync_with_stdio(false);
    cin>>n>>st>>ed>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>from[i]>>to[i]>>val[i];
        add(from[i],to[i],val[i]);
        add(to[i],from[i],val[i]);
    }
    dij();
    int ans=d[ed];
    int anss=inf;
    cin>>k;
    for(int i=0;i<k;i++)
    {
        cin>>u>>v;
        add(u,v,0);
        add(v,u,0);
        dij();
        anss=min(anss,d[ed]);
        cnt=0;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=m;i++)
        {
            add(from[i],to[i],val[i]);
            add(to[i],from[i],val[i]);
        }
    }
    if(ans==anss)
        cout<<"No"<<endl<<ans<<endl;
    else
        cout<<"Yes"<<endl<<anss<<endl;
    return 0;
}

2.开始就算出起点到所有点的最短距离和终点到所有点的最短路,在每次免费线路直接判断是否小就可以。因为是无向边,可以直接算终点到所有点的距离,如果是有向边,只要反向建边再算即可。这个思路只算了两次最短路,明显是上面快很多的。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define inf 0x3f3f3f3f
#include<queue>
using namespace std;
typedef long long ll;
struct node{
    int u,v,w,next;
}e[2050];
struct nd{
    int id;
    int dis;
    bool operator <(const nd &a)const{
        return a.dis<dis;
    }
};
int head[1050],vis[1050],d[1050][1050];
int st,ed,n,m,k,cnt;
void add(int u,int v,int w)
{
    e[cnt].u=u;
    e[cnt].v=v;
    e[cnt].w=w;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
void dij(int start)
{
    priority_queue<nd> q;
    memset(vis,0,sizeof(vis));
    d[start][start]=0;
    while(!q.empty())
        q.pop();
    q.push({start,0});
    while(!q.empty())
    {
        nd t=q.top();
        q.pop();
        int u=t.id;
        if(vis[u])
            continue;
        vis[u]=1;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].v;
            if(!vis[v]&&d[start][v]>d[start][u]+e[i].w)
            {
                d[start][v]=d[start][u]+e[i].w;
                q.push({v,d[start][v]});
            }
        }
    }
}

int main()
{
    int u,v,w,flag=0;
    cnt=0;
    memset(head,-1,sizeof(head));
    std::ios::sync_with_stdio(false);
    cin>>n>>st>>ed>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>u>>v>>w;
        add(u,v,w);
        add(v,u,w);
    }
    memset(d,0x3f,sizeof(d));
    dij(st);//算出起点到所有点的最短路。
    int ans=d[st][ed];
    dij(ed);//算出终点到所有点的最短路
    int anss=inf;
//    for(int i=1;i<=n;i++)
//        cout<<i<<‘ ‘<<d[st][i]<<‘ ‘<<d[ed][i]<<endl;
    cin>>k;

    for(int i=0;i<k;i++)
    {
        cin>>u>>v;
        if(ans>d[st][u]+d[ed][v]||ans>d[st][v]+d[ed][u])//判断是否用免费机票
        {
            anss=min(anss,min(d[st][u]+d[ed][v],d[st][v]+d[ed][u]));
            flag=1;
        }
    }
    if(!flag)
        cout<<"No"<<endl<<ans<<endl;
    else
        cout<<"Yes"<<endl<<anss<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/xiongtao/p/10744889.html

时间: 2024-08-07 08:25:04

E-免费的飞机的相关文章

BZOJ 2763 JLOI 2011 飞行路线 分层图+最短路

题目大意:两个小屁孩要乘飞机去旅行.现在给一些无向边和边权,另外他们还有K次免费乘坐飞机的机会,问从起点到终点的最小话费是什么. 思路:分层图第一题.之前听到分层图还以为是真的建K个图,然后不同层数之间的点连边跑最短路..后来经同学讲解才发现我想多了.. 其实还是动归的思想(最短路不也是动归的思想么(`?ω?′)),f[ i ][ j ]表示在j位置时,已经用了i次免费机会的时候的最小花费,然后在SPFA里多一维的转移就可以了. PS:BZOJ上这个题还是挺卡常数的,我之前用queue用了938

2016年最牛逼的分类Android项目源码免费一次性打包下载!

之前发过一个帖子,但是那个帖子有点问题我就重新发一个吧,下面的源码是我从今年开始不断整理源码区和其他网站上的安卓例子源码,目前总共有810套左右,根据实现的功能被我分成了100多个类,总共接近2.5G,还在不断更新.初学者可以快速方便的找到自己想要的例子,大神也可以看一下别人的方法实现.虽然的例子都是我一个人辛辛苦苦花了很多时间和精力整理的,但是既然这些例子是来自于社区那就让他们免费回归社区吧,(是的!特么的不要一分钱!最看不起那些挂羊头卖狗的)你可以在本帖里面按Ctrl+F查找你需要的关键字,

【Unity Shaders】ShadowGun系列之一——飞机坠毁的浓烟效果

写在前面 最近一直在思考下面的学习该怎么进行,当然自己有在一边做项目一边学OpenGL,偶尔翻翻论文之类的.但是,写shader是一个需要实战和动手经验的过程,而模仿是前期学习的必经之路.很多人都会问,怎么学shader,看什么书.当然我经验也不够,目前的路线是:掌握一门着色语言+读几本经典书籍+学习优秀的shader实例+动手实践+动手实践+动手实践.每一个都不容易,所以学shader是一个漫长而艰辛的过程. 当当当~所以,在继Surface Shader系列之后,我打算学习一下现在已有的各种

android源码大放送(实战开发必备),免费安卓demo源码,例子大全文件详细列表

免费安卓demo源码,例子大全文件详细列表 本列表源码永久免费下载地址:http://www.jiandaima.com/blog/android-demo 卷 yunpan 的文件夹 PATH 列表 卷序列号为 0000-73EC E:. │ jiandaima.com文件列表生成.bat │ 例子大全说明.txt │ 本例子永久更新地址~.url │ 目录列表2016.03.10更新.txt │ ├─前台界面 │ ├─3D标签云卡片热门 │ │ Android TagCloudView云标签

转--2014年最新810多套android源码2.46GB免费一次性打包下载

转载自:http://www.eoeandroid.com/thread-497046-1-1.html 感谢该博客主人无私奉献~~ 下面的源码是从今年3月份开始不断整理源码区和其他网站上的安卓例子源码,目前总共有810套左右,根据实现的功能被博主分成了100多个类,总共接近2.5G,还在不断更新.初学者可以快速方便的找到自己想要的例子,大神也可以看一下别人的方法实现.虽然的例子都是博主一个人辛辛苦苦花了很多时间和精力整理的,但是既然这些例子是来自于社区那就让他们免费回归社区吧,(是的!特么的不

世界杯真品球衣竟然免费拿!!!

世界杯比赛接近尾声,这一场场比赛堪比饕餮盛宴,每天啤酒小菜世界杯,好不欢乐.伴随着世界杯的不仅有赛场上神一样的球员,也不仅有看台上美丽的大胸妹子,还有一样,那就是竞猜! 有人说,竞猜就是赌球,我觉得这个不尽然.就国内的好多博彩网站来说,竞猜就是赌球,虚拟货币,真实货币的转化而已.不是有个哥们热衷赌球,赌的自己的座驾由飞机变成跑车,由跑车变成摩托车,由摩托车变成自行车,最后沦落到上街乞讨-- 但是对于程序员球迷来说,只看球确实是少了那么点意思,本来上班加班就已经十分无聊了,看个球还只能看个胜负,一

Cocos2d-x飞机大战教程笔记

咳咳~跟着大神的教程学做Cocos2d-x的飞机大战...鉴于我是那种跟着教程都会出非常多错的人,所以还是一路跟着做些笔记比較好.并且因为是用课余时间,所以仅仅能断断续续地做,写下来也好让自己别忘记~ 2014/4/22  Day01 从apk解压获取素材.再用TexturePacker拼接成plist和png. 话说TexturePacker是收费的啊...7天免费,还能够申请1年的使用期. 之前看书还看到有个神器叫zwoptex,貌似是免费的.可惜仅仅有Mac版...╮(╯_╰)╭Howev

豪华版飞机大战系列(六)--附源代码

最后一篇讲一下游戏中的主要逻辑推断,在上面的工作都做充分准备后,游戏主要逻辑将变得特别清晰,接下来你会看到全部的逻辑都是那么的清晰自然,由于前面已经做好了充分的准备工作,这里仅仅是整合了前面的工作,略微增加了一些游戏推断元素. 同一时候源代码会在文章最后给出链接地址,源代码托管在github上,全部的东西都是开源免费的,在如今的大环境下.开源才是王道,分享才干双赢,我始终认为这是对的.你有一种思想我有一种思想,交流分享后我们都有了两种思想,何乐而不为呢. 好了,回归正题.游戏主要推断逻辑都在Ga

40款免费开源游戏

开源游戏最大的特点的免费,所以我们玩的开源游戏都是正版游戏,另外开源游戏对外开 放源代码,任何有兴趣的人可以对其改进,其游戏的可玩性,易玩性都会逐步提高,也可以说开源游戏融合了众人智慧,是网友分享的成果.这里搜集了 40款免费开源游戏 ,全部是 WINDOWS版本,喜欢玩游戏的朋友不要错过. 冒险—角色扮演游戏 1.Daimonin 这是一块免费的奇幻网游,总体看游戏在2D MMORPG游戏圈以及低配置游戏圈内是一个不错的选择.玩家在游戏中可体现到不同的游戏经历和开发商独特的游戏设计理念.游戏中

CJOJ 免费航班

Description 小Z在MOI比赛中获得了大奖,奖品是一张特殊的机 票.使用这张机票,可以在任意一个国家内的任意城市之间的免费飞行,只有跨国飞行时才会有额外的费用.小Z获得了一张地图,地图上有城市之间的飞机航班和 费用.已知从每个城市出发能到达所有城市,两个城市之间可能有不止一个航班.一个国家内的每两个城市之间一定有不止一条飞行路线,而两个国家的城市之间只 有一条飞行路线.小Z想知道,从每个城市出发到额外费用最大的城市,以便估算出出行的费用,请你帮助他.当然,你不能通过乘坐多次一个航班增加