zoukankan      html  css  js  c++  java
  • 最短路的应用

    问题 F: 路

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 364  解决: 103
    [提交] [状态] [命题人:admin]

    题目描述

    Farmer John 热衷于散步,每天早上他都要从 1 号仓库走到 n 号仓库。 Farmer John 家的 n 个仓库被 m 条双向道路连通起来,每条道路有一个长度 w。而Farmer John 又不喜欢走路,所以他走的是从 1 号仓库到 n 号仓库的最短路。
    但是 Farmer 的奶牛们总想搞点事情,他们计划着把 m 条道路的其中一条变成原来长度的 2 倍,使得 Farmer John 可能会多走一点路。
    他们想知道,最多能让 Farmer John 多走多少路呢?

    输入

    第一行一个正整数 n,m,表示仓库个数和道路条数。
    接下来 m 行,每行三个正整数,表示每条双向道路的连接的仓库和该双向道路的长度。

    输出

    输出只有一行,表示最多能让 Farmer John 每天早上多走多少路。

    样例输入

    5 7
    2 1 5
    1 3 1
    3 2 8
    3 5 7
    3 4 3
    2 4 7
    4 5 2
    

    样例输出

    2
    

    提示

    一开始的最短路为1→3→4→5,长度为1+3+2=6。
    将连接3和4的边变为原来的两倍,3×2=6。
    改造后的图,最短路为1→3→5,长度为1+7=8。
    多走了8−6=2的路程,可以证明这是最大的答案。
    对于50%的数据,1≤n≤50。
    对于100%的数据,1≤n≤250,1≤m≤25000,1≤w≤106。
    保证没有重边。

    思路:考虑变化长度的路一定在最短路中,所以先找出最短路,对路上每一条权值*2,再跑最短路记录下差值

    问题:虽然思路很明确,但是实现的时候疯狂出问题,最后才发现,每次]找出最短路以后,全局变量pre[]数组已经改变,找初始最短路的for循环就会出错,所以在进入dijstra之前先记录一下pre,因为它会改变;

    修改方法2:写两个dijstra,一个记录pre,另一个不记录即可

    代码如下:

    #include <bits/stdc++.h>
    
    using namespace std;
    const int maxn =300;
    const int inf = 0x3f3f3f3f3f3f3f;
    struct E
    {
        int v,w;
        friend bool operator< (E x,E y)
        {
            return x.w>y.w;
        }
    };
    vector <E> edge[maxn];
    int dis[maxn],vis[maxn],milen;
    int pre[maxn];
    void dijheap(int s,int n)
    {
        priority_queue <E> Q;
        memset(vis,0,sizeof(vis));
        memset(pre,0,sizeof(pre));
        for (int i=0; i<=n; i++)
            dis[i]=inf;
        Q.push({s,0});
        dis[s]=0;
        while(!Q.empty())
        {
            E cur=Q.top();//保证取出的队首元素就是距离s最近的
            Q.pop();
            int cv=cur.v;
            if (vis[cv]) continue;
            vis[cv]=1;
            int num=edge[cv].size();
            for (int i=0;i<num;i++)//用这个点去扩展relax
            {
                int v=edge[cv][i].v,w=edge[cv][i].w;
                if (!vis[v])
                {
                    if (dis[v]>dis[cv]+w)
                    {
                        dis[v]=dis[cv]+w;
                        Q.push({v,dis[v]});
                        pre[v]=cv;
                    }
                }
            }
        }
    }
    int findway(int s,int t,int n)
    {
        int ret=0;
        for (int i=t;i!=s;)
        {
            for (int j=0;j<edge[pre[i]].size();j++)
            {
                if (edge[pre[i]][j].v==i)
                {
                    //printf("%d %d %d
    ",i,pre[i],edge[pre[i]][j].w);
                    edge[pre[i]][j].w*=2;
                    int p=pre[i];
                    dijheap(1,n);
                    edge[p][j].w/=2;
                    i=p;
                    ret=max(ret,dis[n]-milen);
                    break;
                }
            }
        }
        return ret;
    }
    int main()
    {
        int n,m;
        //freopen("10.in","r",stdin);
        cin>>n>>m;
        for (int i=0;i<m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            edge[u].push_back({v,w});
            edge[v].push_back({u,w});
        }
        dijheap(1,n);
        milen=dis[n];
        //cout<<milen<<endl;
        int ans=findway(1,n,n);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    MYSQL一对多,两表查询合并数据
    bootstrap瀑布流代码
    os mac apache+php+mysql环境配置
    centos 6.5 服务器安装 (LNMP ntfs文件支持 PHP-RPM CHROOT沙盒)
    在linux下将当前目录文件全部小写含目录名
    Javascript知识汇总------js中容易被忽略的细节(持续更新)
    Javascript知识汇总------js数据类型隐式转换
    下次要写约瑟夫和并查集
    --wrong answer
    --最小生成树
  • 原文地址:https://www.cnblogs.com/ztdf123/p/11314096.html
Copyright © 2011-2022 走看看