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;
}
原文地址:https://www.cnblogs.com/zzyh/p/7601923.html