Shortest Path record (template)

Description: https://www.luogu.com.cn/problem/P2176

Every morning, FJ from their homes across the farm went to the bullpen. Agricultural farms consisting of N blocks, M are connected by bi-directional farm road, each road has a certain length. FJ house No. 1 field, the field number N in the cow. The two fields are not connected to a plurality of roads to the appropriate path for any pair of sequence always walk on the farm field. When another piece when FJ come from a field, always with a total path length of the shortest road to go order.

FJ cattle do, always ill-wishers, decided to interfere with his plans each morning. They are placed in a stack of straw on a road M, so that doubling the length of the road. Cattle hope you follow a path interference makes FJ road from home to the largest increase in the bullpen long. They ask you to design and tell them how much the maximum increment.


The most obvious short circuit. We can choose a way to double the right side.

Simple, I will enumerate violence (● ∀ ●)

That would timeout

Consider which side is not enumerated.

If you do not put straw on the shortest way to the original FJ go, it must be invalid, after all, FJ only take the most short-circuited.

Then we need to record the shortest path, and then enumerate through the shortest side, pitted shortest.

    IF (DIS [e.to]> DIS [ans.num] + EW) { 
                pre [e.to] = I; fr [e.to] = ans.num; // node precursor

In the original, based on the addition of this. fr array record is the precursor of the target point. Finally, a target point is n, then we can always find a follow up.

pre array record corresponding to each of the slack node, after all, we want to operate on the edge.

    int now=n,nu=0;
    while(now!=1){
        that[++nu]=pre[now];
        now=fr[now];
    } 

Then we started descending put into that array.

Enumeration modified side edge right, because it is undirected edges, so one should modify the pros and cons on both sides.

For example, path record is numbered side 3, then in fact the edge No. 4 should also be amended. The record is 4 No. 3 should also be amended.

Why? Time map building is attached to two sides exist Well ~

#include<iostream>
#include<cstring>
#include<cstdio>
#define M 15000
#include<queue> 
#define N 110
using namespace std;
int n,m;
int po,ans;
int head[N],to[M],next[M],len[M],e=1;
void buid(int u,int v,int l)
{
    next[++e]=head[u],head[u]=e;
    to[e]=v,len[e]=l;
}
int dis[N],init[N];
int pre[N],fr[N],that[M],nu;
queue<int> q;
void spfa(int s)
{
    memset(dis,20,sizeof(dis));
    dis[s]=0;init[s]=1,q.push(s);
    while(!q.empty())
    {
        int now=q.front();q.pop();init[now]=0;
        for(int i=head[now];i;i=next[i])
        {
            int j=to[i];
            if(dis[j]>dis[now]+len[i])
            {
                dis[j]=dis[now]+len[i];
                pre[j]=i;fr[j]=now;
                if(!init[j])
                {
                    init[j]=1;q.push(j);
                }
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i)
    {
        int u,v,l;
        scanf("%d%d%d",&u,&v,&l);
        buid(u,v,l);
        buid(v,u,l);
    }
    spfa(1);po=dis[n];
    int now=n;
    while(now!=1)
    {
        that[++nu]=pre[now];//记路径
        now=fr[now];
    }
    for(int i=1;i<=nu;++i)//枚举路径
    {
        len[that[i]]*=2;
        len[that[i]^1]*=2;
        spfa(1);//操♂作
        ans=max(ans,dis[n]);
        len[that[i]]/=2;
        len[that[i]^1]/=2;
    }
    cout<<ans-po<<endl;//end
    return 0;
} 
View Code

 

Guess you like

Origin www.cnblogs.com/iss-ue/p/12524422.html