【次短路模板】习题

一.模板

dis[t][0]:表示 s ss 到 t tt 的最短路;

dis[t][1] dis[t][1]dis[t][1]:表示 s ss 到 t tt 的次短路;

堆优化的Dijkstra模板

#include<bits/stdc++.h>
using namespace std;
#define maxn 1000010
#define INF 0x3f3f3f3f
typedef long long ll;
typedef pair<ll,int>pii;
struct Edge{
    int to,nxt;
    ll w;
}edge[maxn<<2];
ll dis[maxn][2];
int n,m,s,t,tot=0,vis[maxn],head[maxn];
void add(ll u,ll v,ll w){
    edge[++tot].to=v; edge[tot].w=w; edge[tot].nxt=head[u]; head[u]=tot;
    edge[++tot].to=u; edge[tot].w=w; edge[tot].nxt=head[v]; head[v]=tot;
}
void Dijkstra(){
    for(int i=0;i<=n;i++) dis[i][0]=dis[i][1]=INF;
    dis[s][0]=0;
    priority_queue<pii,vector<pii>,greater<pii> >que;
    que.push(pii(0,s));
    while(!que.empty()){
        pii p=que.top();
        que.pop();
        if(p.first>dis[p.second][1]) continue;
        for(int i=head[p.second];~i;i=edge[i].nxt){
            ll d=p.first+edge[i].w;
            if(dis[edge[i].to][0]>d){//更新最短路
                swap(dis[edge[i].to][0],d);//交换!!!
                que.push(pii(dis[edge[i].to][0],edge[i].to));//注意d值已经被交换了
            }
            if(dis[edge[i].to][1]>d&&dis[edge[i].to][0]<d){//更新次短路
                dis[edge[i].to][1]=d;
                que.push(pii(d,edge[i].to));
            }
        }
    }
}
int main(){
    tot=0,memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        ll u,v,w; scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w);
    }
    scanf("%d%d",&s,&t); //起点,终点 
    Dijkstra();
    printf("%lld %lld\n",dis[t][0],dis[t][1]);//最短路,次短路 
    return 0;
}
View Code

第二种版本:

#include <bits/stdc++.h>
using namespace std;
#define res register int 
#define inf 0x3f3f3f3f
const int maxn=5005;
int N,M,ans=1;
int head[maxn];
int dis1[maxn],dis2[maxn];
struct Node{
    int x,sum;
};
bool operator<(const Node a,const Node b){
    return a.sum>b.sum;
}
struct edge{
    int to,next,val;
}e[100005*2];
 
void add(int x,int y,int val){
    e[ans].to=y;
    e[ans].val=val;
    e[ans].next=head[x];
    head[x]=ans++;
}
 
void dijkstra()
{
    priority_queue<Node> q;
    q.push((Node){1,0});
    while(!q.empty()){
        Node now=q.top();
        q.pop();
        int from=now.x,sum=now.sum;
        if(dis2[from]<sum) continue;//加上了这个神奇的东西。 
        for(res i=head[from];i;i=e[i].next){
            int to=e[i].to;
            int temp=sum+e[i].val;
            if(dis1[to]>temp){
                swap(dis1[to],temp);
                q.push((Node){to,dis1[to]});    
            }
            if(dis2[to]>temp&&dis1[to]<temp){
                dis2[to]=temp;
                q.push((Node){to,dis2[to]});
            }
        }
    }
} 
 
void init()
{
    scanf("%d%d",&N,&M);
    int v1,v2,val;
    for(res i=1;i<=M;i++){
        scanf("%d%d%d",&v1,&v2,&val);
        add(v1,v2,val);
        add(v2,v1,val);
    }
    fill(dis1,dis1+N+1,inf);
    fill(dis2,dis2+N+1,inf);
    dis1[1]=0;
}
int main()
{
    init();
    dijkstra();
    printf("%d",dis2[N]);
    return 0;
}
View Code

spfa模板

#include<bits/stdc++.h>
using namespace std;
#define maxn 1000010
#define INF 0x3f3f3f3f
typedef long long ll;
struct Edge{
    int to,nxt;
    ll w;
}edge[maxn<<2];
ll dis[maxn][2];
int n,m,s,t,tot=0,vis[maxn],head[maxn];
void add(ll u,ll v,ll w){
    edge[++tot].to=v; edge[tot].w=w; edge[tot].nxt=head[u]; head[u]=tot;
    edge[++tot].to=u; edge[tot].w=w; edge[tot].nxt=head[v]; head[v]=tot;
}
void spfa(){
    for(int i=1;i<=n;i++) vis[i]=0,dis[i][0]=dis[i][1]=INF;
    dis[s][0]=0;
    queue<int>q; q.push(s); vis[s]=1;
    while(!q.empty()){
        int u=q.front(); q.pop(); vis[u]=0;
        for(int i=head[u];~i;i=edge[i].nxt){
            ll v=edge[i].to,w=edge[i].w;
            if(dis[v][0]>dis[u][0]+w){
                dis[v][1]=dis[v][0];
                dis[v][0]=dis[u][0]+w;
                if(!vis[v]){
                    vis[v]=1; q.push(v);
                }
            }
            if(dis[v][1]>dis[u][0]+w && dis[u][0]+w>dis[v][0]){
                dis[v][1]=dis[u][0]+w;
                if(!vis[v]){
                    vis[v]=1; q.push(v);
                }
            }
            if(dis[v][1]>dis[u][1]+w){
                dis[v][1]=dis[u][1]+w;
                if(!vis[v]){
                    vis[v]=1; q.push(v);
                }
            }
        }
    }
}
int main(){
    tot=0,memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        ll u,v,w; scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w);
    }
    scanf("%d%d",&s,&t); 
    spfa();
    printf("%lld %lld\n",dis[t][0],dis[t][1]);
    return 0;
}
View Code

二.习题

1.P2865 [USACO06NOV]路障Roadblocks   ---三种都行   去掉最短路的输出

#include<bits/stdc++.h>
using namespace std;
#define maxn 1000010
#define INF 0x3f3f3f3f
typedef long long ll;
struct Edge{
    int to,nxt;
    ll w;
}edge[maxn<<2];
ll dis[maxn][2];
int n,m,s,t,tot=0,vis[maxn],head[maxn];
void add(ll u,ll v,ll w){
    edge[++tot].to=v; edge[tot].w=w; edge[tot].nxt=head[u]; head[u]=tot;
    edge[++tot].to=u; edge[tot].w=w; edge[tot].nxt=head[v]; head[v]=tot;
}
void spfa(){
    for(int i=1;i<=n;i++) vis[i]=0,dis[i][0]=dis[i][1]=INF;
    dis[s][0]=0;
    queue<int>q; q.push(s); vis[s]=1;
    while(!q.empty()){
        int u=q.front(); q.pop(); vis[u]=0;
        for(int i=head[u];~i;i=edge[i].nxt){
            ll v=edge[i].to,w=edge[i].w;
            if(dis[v][0]>dis[u][0]+w){
                dis[v][1]=dis[v][0];
                dis[v][0]=dis[u][0]+w;
                if(!vis[v]){
                    vis[v]=1; q.push(v);
                }
            }
            if(dis[v][1]>dis[u][0]+w && dis[u][0]+w>dis[v][0]){
                dis[v][1]=dis[u][0]+w;
                if(!vis[v]){
                    vis[v]=1; q.push(v);
                }
            }
            if(dis[v][1]>dis[u][1]+w){
                dis[v][1]=dis[u][1]+w;
                if(!vis[v]){
                    vis[v]=1; q.push(v);
                }
            }
        }
    }
}
int main(){
    tot=0,memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        ll u,v,w; scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w);
    }
    s=1,t=n; 
    spfa();
    printf("%lld\n",dis[t][1]);
    return 0;
}
View Code

 

posted @ 2019-10-19 16:02  saaas  阅读(135)  评论(0)    收藏  举报