• P2176 [USACO14FEB]路障Roadblock


    题目描述

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

    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

    说明

    【样例说明】

    若使 3 和 4 之间的道路长加倍,最短路将由 1-3-4-5 变为 1-3-5。

    【数据规模和约定】

    对于 30%的数据,N <= 70,M <= 1,500。

    对于 100%的数据,1 <= N <= 100,1 <= M <= 5,000,1 <= L_i <= 1,000,000。

    题目大意:求将1--n上最短路的某条边的边权*2后新的最短路与原最短路长度差最大是多少

    题解:暴力枚举最短路的每一条边*2再跑最短路取max

    代码:

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    
    queue<int>q;
    int n,m,sumedge,cnt,cur,ans;
    int head[110],pre[110],cut[1100],bege[1100],dis[110],inq[110];
    
    struct Edge{
        int x,y,z,nxt;
        Edge(int x=0,int y=0,int z=0,int nxt=0):
            x(x),y(y),z(z),nxt(nxt){}
    }edge[5002*2];
    
    void add(int x,int y,int z){
        edge[++sumedge]=Edge(x,y,z,head[x]);
        head[x]=sumedge;
    }
    
    int spfa(){
        memset(dis,127/3,sizeof(dis));
        memset(inq,0,sizeof(inq));
        while(!q.empty())q.pop();
        q.push(1);dis[1]=0;inq[1]=1;
        while(!q.empty()){
            int now=q.front();q.pop();inq[now]=0;
            for(int i=head[now];i;i=edge[i].nxt){
                int v=edge[i].y;
                if(dis[v]>dis[now]+edge[i].z){
                    dis[v]=dis[now]+edge[i].z;
                    pre[v]=now;bege[v]=i;
                    if(!inq[v]){
                        inq[v]=1;
                        q.push(v);
                    }
                }
            }
        }
        return dis[n];
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);add(y,x,z);
        }
        cur=spfa();
    //    cout<<dis[3]<<" "<<dis[4]<<endl;
        for(int i=n;i;i=pre[i])
            cut[++cnt]=bege[i];
        for(int i=1;i<=cnt;i++){
            int k=cut[i];
        //    cout<<k<<endl;
            if(k&1){
                edge[k].z*=2;
                edge[k+1].z*=2;
            }else {
                edge[k].z*=2;
                edge[k-1].z*=2;
            }
            ans=max(ans,spfa());
            if(k&1){
                edge[k].z/=2;
                edge[k+1].z/=2;
            }else{
                edge[k].z/=2;
                edge[k-1].z/=2;
            }
        }
    //    cout<<ans<<" "<<cur<<endl;
        cout<<ans-cur<<endl;
        return 0;
    }
  • 相关阅读:
    AwaitAsync(异步和多线程)
    Newtonsoft.Json高级用法
    C# DataTable 去重复数据方法
    C# List 根据对象属性去重的四种方法对比
    C# <T>泛型的使用
    LeetCode 368. Largest Divisible Subset
    LeetCode 357. Count Numbers with Unique Digits
    LeetCode 350. Intersection of Two Arrays II
    LeetCode 349. Intersection of Two Arrays
    LeetCode 344. Reverse String
  • 原文地址:https://www.cnblogs.com/zzyh/p/7601923.html
Copyright © 2020-2023  润新知