最短路+是否经过指定的边

题目链接:https://ac.nowcoder.com/acm/contest/699/E
输入:
输入 n, s, t;
输入m
m条边。
输入k
k条边(边权=0)。

问:现在可以经过k条免费边的一条,求s到t的最短路是否要经过一条。如果经过输出Yes,和最小费用。否则输出No,和最小费用(1<=n, m, k<=1000)。

思路:把没有添加k条免费边的图跑一次最短路,费用:ans1。然后每次添加一条,并且删除上次添加的那条。跑最短路,费用:ans2=min(ans2, dijkstra(s, t))。

然后比较:ans1和ans2。

if(ans1>ans2)
    {
        printf("Yes\n");
        printf("%d\n",ans2);
    }
    else
    {
        printf("No\n");
        printf("%d\n",ans2);
    }
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=205;

vector< pair<int ,int > > e[maxn];
int n, m;
int dis[maxn];   //dis当前的最短路
int vis[maxn];   //是否已经求出最短路

priority_queue<pair<int, int> > q;
int dijkstra(int s, int t)
{
    memset(vis, 0, sizeof(vis));
    memset(dis, 3, sizeof(dis));
    while(!q.empty())
    {
        q.pop();
    }
    dis[s]=0;
    q.push(make_pair(-dis[s], s));
    while(!q.empty())
    {
        int now=q.top().second;                //一定是最短路上的顶点
        q.pop();
        if(vis[now])
        {
            continue;
        }
        vis[now]=1;
        for(int i=0;i<e[now].size();i++)       //访问所有的邻接点
        {
            int v=e[now][i].first;
            if(!vis[v]&&dis[v]>dis[now]+e[now][i].second)
            {
                dis[v]=dis[now]+e[now][i].second;
                q.push(make_pair(-dis[v], v));//把可能的最短路顶点加入队列
            }
        }
    }

    return dis[t];

}

int main()
{
    int s, t;
    scanf("%d%d%d",&n,&s,&t);
    scanf("%d",&m);

    int x, y, z;
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        e[x].push_back(make_pair(y ,z));
        e[y].push_back(make_pair(x ,z));
    }
    int ans1=dijkstra(s, t);
    int ans2=ans1;
    scanf("%d",&m);
    int u, v, uu, vv;
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&u,&v);
        if(i==0)
        {
            e[u].push_back(make_pair(v ,0));
            e[v].push_back(make_pair(u ,0));
            uu=u,vv=v;
        }
        else
        {
            e[uu].pop_back();
            e[vv].pop_back();
            e[u].push_back(make_pair(v ,0));
            e[v].push_back(make_pair(u ,0));
            uu=u,vv=v;
        }
        ans2=min(ans2, dijkstra(s, t));
    }
    if(ans1>ans2)
    {
        printf("Yes\n");
        printf("%d\n",ans2);
    }
    else
    {
        printf("No\n");
        printf("%d\n",ans2);
    }

    return 0;
}

全部评论

相关推荐

会飞的猿:我看你想进大厂,我给你总结一下学习路线吧,java语言方面常规八股要熟,那些java的集合,重点背hashmap八股吧,jvm类加载机制,运行时分区,垃圾回收算法,垃圾回收器CMS、G1这些,各种乐观锁悲观锁,线程安全,threadlocal这些。在进阶一些的比如jvm参数,内存溢出泄漏排查,jvm调优。我这里说的只是冰山一角,详细八股可以去网上找,这不用去买,都免费资源。mysql、redis可以去看小林coding,我看你简历上写了,你一定要熟,什么底层b+树、索引结构、innodb、mvcc、undo log、redo log、行级锁表级锁,这些东西高频出现,如果面试官问我这些我都能笑出来。消息队列rabbitmq也好kafka也好,学一种就行,什么分区啊副本啊确认机制啊怎么保证不重复消费、怎么保证消息不丢失这些基本的一定要会,进阶一点的比如LEO、高水位线、kafka和rocketmq底层零拷贝的区别等等。计算机网络和操作系统既然你是科班应该理解起来问题不大,去看小林coding这两块吧,深度够了。spring boot的八股好好看看吧,一般字节腾讯不这么问,其他的java大厂挺爱问的,什么循环依赖啥的去网上看看。数据结构的话科班应该问题不大,多去力扣集中突击刷题吧。项目的话其实说白了还是结合八股来,想一想你写的这些技术会给你挖什么坑。除此之外,还有场景题、rpc、设计模式、linux命令、ddd等。不会的就别往简历上写了,虽然技术栈很多的话好看些,但背起来确实累。总结一下,多去实习吧,多跳槽,直到跳到一个不错的中厂做跳板,这是一条可行的进大厂的路线。另外,只想找个小厂的工作的话,没必要全都照这些准备,太累了,重点放在框架的使用和一些基础八股吧。大致路线就这样,没啥太多难度,就是量大,你能达到什么高度取决于你对自己多狠,祝好。
点赞 评论 收藏
分享
码农索隆:我头回见校招简历把个人优势写在最前面的,是我老了吗
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务