zoukankan      html  css  js  c++  java
  • P2176 [USACO14FEB]路障Roadblock

    题目描述

    每天早晨,FJ从家中穿过农场走到牛棚。农场由 N 块农田组成,农田通过 M 条双向道路连接,每条路有一定长度。FJ 的房子在 1 号田,牛棚在 N 号田。没有两块田被多条道路连接,以适当的路径顺序总是能在农场任意一对田间行走。当FJ从一块田走到另一块时,总是以总路长最短的道路顺序来走。

    FJ 的牛呢,总是不安好心,决定干扰他每天早晨的计划。它们在 M 条路的某一条上安放一叠稻草堆,使这条路的长度加倍。牛希望选择一条路干扰使得FJ 从家到牛棚的路长增加最多。它们请你设计并告诉它们最大增量是多少。

    输入输出格式

    输入格式:

    第 1 行:两个整数 N, M。

    第 2 到 M+1 行:第 i+1 行包含三个整数 A_i, B_i, L_i,A_i 和 B_i 表示道路 i 连接的田的编号,L_i 表示路长。

    输出格式:

    第 1 行:一个整数,表示通过使某条路加倍而得到的最大增量。

    输入样例#1: 复制
    5 7
    2 1 5
    1 3 1
    3 2 8
    3 5 7
    3 4 3
    2 4 7
    4 5 2
    输出样例#1: 复制
    2


    刚看完第一段以为是一道普通的最短路,看到后面。emmmmm...
    同学提醒说是最短路径树,然而并不会那么高深的东西qaq,只能用简单的思想去捣鼓了。
    听了别人的想法,Dijksra中,在每次松弛时时记录一下v和他的前驱节点u,这样就能逆向回溯出从x到n的最短路径了。
    同时记得区分第一次和之后的Dijkstra,注意只有第一次Dijkstra时记录松弛的路径,以防之后错误修改第一次时记录好的最短路径;
    暴力最短路径中每一条倍增所产生的影响,然后取其中的最大值与第一次求差,得出结果。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int MAX_V= 205;
    const int MAX_E= 20000;
    const int inf= 0x3f3f3f3f;
    struct ENode
    {
        int to;
        int w;
        int next;
    };
    ENode Edegs[MAX_E];
    int Head[MAX_V], cnt;         //cnt: 边计数器;
    int Dis[MAX_V];
    int Front[MAX_V];             //Front[v]: 最短路径中v的前置节点u;
    pair<int, int> E_double_cost; //连接这两点的边,其权值加倍;
    bool flag;                    //flag记录是否为初次求最短路;
    void Add_Edge_0 (int a, int b, int w)
    {
        //有向图建边;
        ++ cnt;
        Edegs[cnt].to= b;
        Edegs[cnt].w= w;
        Edegs[cnt].next= Head[a];
        Head[a]= cnt;
    }
    void Add_Edge_1 (int a, int b, int w)
    {
        //无向图建边;
        ++ cnt;
        Edegs[cnt].to= b;
        Edegs[cnt].w= w;
        Edegs[cnt].next= Head[a];
        Head[a]= cnt;
        ++ cnt;
        Edegs[cnt].to= a;
        Edegs[cnt].w= w;
        Edegs[cnt].next= Head[b];
        Head[b]= cnt;
    }
    struct cmpx
    {
        bool operator()(int &a, int &b)const
        {
            return Dis[a]- Dis[b]> 0;
        }
    };
    void Dijkstra(int x)
    {
        priority_queue<int, vector<int>, cmpx> q;
        memset(Dis, inf, sizeof(Dis));
        Dis[x]= 0;
        Front[x]= -1;  //x 的前驱节点为-1;
        q.push(x);
    
        while (! q.empty())
        {
            int u= q.top();
            q.pop();
            for (int k= Head[u]; k!= -1; k= Edegs[k].next )
            {
                int v= Edegs[k].to;
                if(!flag && u== E_double_cost.first&& v== E_double_cost.second )
                {
                    //边E(u->v)的花费被加倍了;
                    if (Dis[v]> Dis[u]+ Edegs[k].w+ Edegs[k].w )
                    {
                        Dis[v]= Dis[u]+ Edegs[k].w+ Edegs[k].w;
                        q.push(v);
                    }
                }
                else
                {
                    if (Dis[v]> Dis[u]+ Edegs[k].w )
                    {
                        Dis[v]= Dis[u]+ Edegs[k].w;
                        if (flag) Front[v]= u;
                        q.push(v);
                    }
                }
            }
        }
    }
    
    int main()
    {
        int n, m;
        cin >>n >>m;
        int a, b, w;
        cnt= -1;
        memset(Head, -1, sizeof(Head));
        for (int i= 0; i< m; i ++)
        {
            cin >>a >>b >>w;
            Add_Edge_1(a, b, w);
        }
        flag= true;
        Dijkstra(1);
        flag= false;
        int tmp= Dis[n];   //第一次时到n的最短路距离;
        int far= tmp;      //保存修改后到n的最短路距离;
        for (int i= n; i!= 1; i= Front[i] )
        {
            E_double_cost.first= Front[i];
            E_double_cost.second= i;
            Dijkstra(1);
            far= max(far, Dis[n]);
        }
        cout <<far- tmp <<endl;
        return 0;
    }
     
  • 相关阅读:
    video 自动循环播放
    C. Kefa and Park
    B. Random Teams(数学题)
    B. Books(水题)
    dd爱科学1.0(牛客)
    B. WeirdSort
    B. The Cake Is a Lie
    优先队列 priority_queue
    C. A-B Palindrome
    B. Fedor and New Game(位运算)
  • 原文地址:https://www.cnblogs.com/Amaris-diana/p/10555354.html
Copyright © 2011-2022 走看看