洛谷 P2176(最短路)

###题目链接 洛谷 P2176 ###

题目大意:

已知农夫从 1 走到 N 点,一定走的是最短路。问你将某条路的长度变为其两倍后,农夫从 1 走到 N 点的路程最大增加多少,输出最大增量。

分析:

1、很显然,如果增大某条路长度会使得最短路增加,那么这条路必为原先最短路径上的某条路。

2、故只需要记录边的 id ,然后依次枚举该条路长度翻倍后的最短路径,然后取与一开始最短路的差值的最大值即可。

3、记得用 id[] 存储路径编号,然后要分别更改这条路径两个方向的边的值(因为是无向边)。

4、时间复杂度应该是 N * M * logM ,本题大约为 107 ,1s 应该够了。

代码如下:

#define IO freopen("test.in","r",stdin),freopen("test.out","w",stdout)
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define inf 0x3f3f3f3f
#define maxn 108
typedef pair<int,int> P;
int n,m,cnt;
int head[maxn],dist[maxn],pre[maxn],id[maxn],a[maxn];
bool vis[maxn];
struct Edge
{
    int to;
    int val;
    int next;
}edge[10008];
inline void add(int u,int v,int w)
{
    edge[++cnt].to=v;
    edge[cnt].val=w;
    edge[cnt].next=head[u];
    head[u]=cnt;
    return;
}
int dijkstra()
{
    for(int i=1;i<=n;i++) dist[i]=inf,vis[i]=false;
    priority_queue<P,vector<P>,greater<P> > q;
    while(!q.empty()) q.pop();
    q.push(make_pair(0,1));
    dist[1]=0;
    while(!q.empty())
    {
        int u=q.top().second,t=q.top().first;
        q.pop();
        if(vis[u]) continue;
        if(u==n) return dist[n];
        vis[u]=true;
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].to;
            if(dist[v]>dist[u]+edge[i].val){
                dist[v]=dist[u]+edge[i].val;
                pre[v]=u,id[v]=i;
                q.push(make_pair(dist[v],v));
            }
        }
    }
    return dist[n];
}
int main()
{
    //IO;
    scanf("%d%d",&n,&m);
    int A,B,C;
    while(m--)
    {
        scanf("%d%d%d",&A,&B,&C);
        add(A,B,C),add(B,A,C);
    }
    int s=dijkstra();
    int x=n;
    cnt=0;
    while(id[x]){
        a[++cnt]=id[x];
        x=pre[x];
    }
    int ans=-1;
    for(int i=1;i<=cnt;i++){
        if(a[i]%2==0){
            edge[a[i]-1].val*=2,edge[a[i]].val*=2;
            int res=dijkstra();
            ans=max(ans,res-s);
            edge[a[i]-1].val/=2,edge[a[i]].val/=2;
        }
        else{
            edge[a[i]].val*=2,edge[a[i]+1].val*=2;
            int res=dijkstra();
            ans=max(ans,res-s);
            edge[a[i]].val/=2,edge[a[i]+1].val/=2;
        }
    }
    printf("%d
",ans );
}
原文地址:https://www.cnblogs.com/Absofuckinglutely/p/11504487.html