[kuangbin带你飞]专题四【最短路练习】(dij)

建议做题顺序:
(其实数据量小一般floyd,但其他方法也是可以的)
dijk: 1 (7 ) 4 10 3 (2) 16

spfa:(10) 12 13 5 15 18

floyd: 6 7 9 2 14

差分约束:19 11

最后剩下一个第17题,涉及网络流,留在网络流专题做。
做题顺序来自传送门

Til the Cows Come Home (poj2387)

在这里插入图片描述
在这里插入图片描述

Sample Input

5 5
1 2 20
2 3 30
3 4 20
4 5 20
1 5 100

Sample Output

90

板子题不多赘述。

  1. 本题用到了邻接表存(可以存的下)(链式前向星存图,+ dij
    这样不用考虑重边
  2. 本题的输入是先边,后节点数

对于不懂链式前向星的,我推荐一篇blog(链式前向星是邻接表的一种)

传送门

AC

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#define fzhead EDGE(int _to, int _v, int _next)
#define fzbody to(_to), v(_v), next(_next)
#define For(i,x,y) for (register int i=(x);i<=(y);i++)
#define FOR(i,x,y) for (register int i=(x);i<=(y);i++)
#define mp make_pair
#define fi first
#define se second
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int, int>pa;
typedef pair<ll,ll>PA;
inline int read()
{
    int ans=0;
    char c=getchar();bool neg=false;
    while(c<'0'||c>'9')
    {
        if(c=='-')neg=true;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        ans=ans*10+c-'0';
        c=getchar();
    }
    return (neg)?-ans:ans;
}
void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
const int maxn=1e3+10;
int head[maxn<<1], dis[maxn], vis[maxn];
int cnt,n,m;
struct EDGE
{
    int to,next,v;
    EDGE(){}
    fzhead:fzbody{}
}e[maxn<<1];
void add(int bg, int ed, int v)
{
    e[++cnt]=EDGE(ed, v, head[bg]);
    head[bg]=cnt;
}
inline void dij(int s)
{
    For(i, 1, n)vis[i]=0;
    priority_queue<pa>q;
    dis[s]=0;q.push(mp(0,s));
    while(!q.empty())
    {
        int u=q.top().se;
        q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int i=head[u]; i!=-1; i=e[i].next)
        {
            if(dis[e[i].to]>dis[u]+e[i].v)
            {
                dis[e[i].to]=dis[u]+e[i].v;
                q.push(mp(-dis[e[i].to],e[i].to));
            }
        }
    }
}
int main()
{
    m=read(),n=read();
    memset(dis,0x3f,sizeof(dis));
    memset(head, -1, sizeof(head));
    For(i,1,m)
    {
        int x=read(),y=read(),v=read();
        add(x,y,v);
        add(y,x,v);
    }
    dij(n);
    write(dis[1]);
    return 0;
}

MPI Maelstrom (poj1502)

(floyd板子题,加一个stl读数据)
在这里插入图片描述
在这里插入图片描述

Sample Input

5
50
30 5
100 20 50
10 x x 10

Sample Output

35

预备知识

atoi和stoi的区别
①atoi()的参数是 const char* ,因此对于一个字符串str我们必须调用 c_str()的方法把这个string转换成 const char类型的,而stoi()的参数是const string,不需要转化为 const char*;
②stoi()会做范围检查,默认范围是在int的范围内的,如果超出范围的话则会runtime error!而atoi()不会做范围检查,如果超出范围的话,超出上界,则输出上界,超出下界,则输出下界
————————————————
版权声明:本文为CSDN博主「liuwxye」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_30366449/article/details/97921986

  1. atoi(s) 是STL的一个函数,可以把一个字符数组s转化成整型数字。
  2. atoi对应char,stoi 对应string
  3. 数据小,直接floyd

哎,读题读半天英语还是不过关。。
本题求如何可以从1到所有其他节点的路径最小。
先求一遍单源最短路之后。
之后求出最短路的最大值。

AC(floyd)

#include <iostream>
#include <algorithm>
#include  <cstdio>
#include <cstring>
using namespace std;
const int INF=0x3f3f3f3f;
char s[110];
int cost[110][110];
int n;
int main()
{
    cin>>n;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
            cost[i][j]=(i==j)?0:INF;//init
    }
    for(int i=2; i<=n; i++)
    {
        for(int j=1; j<i; j++)
        {
            scanf("%s",s);
            if(s[0]!='x')cost[i][j]=cost[j][i]=atoi(s);
        }
    }
    for(int k=1; k<=n; k++)
    {
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                cost[i][j]=min(cost[i][j],cost[i][k]+cost[k][j]);
            }
        }
    }
    int ans=0;
    for(int i=1; i<=n; i++)
        if(cost[1][i]!=INF)ans=max(cost[n][i],ans);
    cout<<ans<<endl;
    return 0;
}

AC(dij)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#define fzhead EDGE (int _to, int _v, int _next)
#define fzbody to(_to), v(_v), next(_next)
#define For(i,x,y) for (register int i=(x); i<=(y); i++)
#define mp make_pair
#define fi first
#define se second
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int>pa;
typedef pair<ll,ll>PA;
const int maxn=1e5+10;
inline int read()
{
    int ans=0;bool neg=false;
    char c=getchar();
    while(c>'9'||c<'0')
    {
        neg=true;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        ans=ans*10+c-'0';
        c=getchar();
    }
    return (neg)?-ans:ans;
}
void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
struct EDGE
{
    int to,next,v;
    EDGE(){}
    fzhead : fzbody{}
}e[maxn];
int n,m,cnt;
int vis[maxn],dis[maxn],head[maxn];
void add(int bg, int ed, int v)
{
    e[++cnt]=EDGE(ed,v,head[bg]),head[bg]=cnt;
}
inline void dij(int s)
{
    For(i,1,n)vis[i]=0;
    priority_queue<pa>q;
    dis[s]=0;q.push(mp(0,s));
    while(!q.empty())
    {
        int u=q.top().se;
        q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int i=head[u]; i!=-1; i=e[i].next)
        {
            if(dis[e[i].to]>dis[u]+e[i].v)
            {
                dis[e[i].to]=dis[u]+e[i].v;
                q.push(mp(-dis[e[i].to],e[i].to));
            }
        }
    }
}
int main()
{
    int n;
    memset(dis,0x3f,sizeof(dis));
    memset(head,-1,sizeof(head));
    n=read();
    char s[100];
    for(int i=2; i<=n; i++)
    {
        for(int j=1; j<i; j++)
        {
            scanf("%s",s);
            if(s[0]!='x')
            {
                int cost=atoi(s);
                add(i,j,cost);
                add(j,i,cost);
            }
        }
    }
  //  cout<<"ok"<<endl;
    dij(1);
    int ans=0;
    for(int i=1; i<=n; i++)
    {
        ans=max(dis[i],ans);
    }
   // cout<<"ok"<<endl;
    write(ans);
    putchar('\n');
    return 0;
}

Silver Cow Party(poj3268)

在这里插入图片描述
在这里插入图片描述

Sample Input

4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3

Sample Output

10

题意:

本题描述了有n头牛要去参加一个party。
题目中每头牛分布在每个节点上,有一个节点x是聚会的举办地点。
n头牛要去参加聚会,牛门都很聪明,会走最短路。(有m条边即m条路)
题目中的路都是有向的。求在所有牛中,哪头牛来回的时间最长(路程)。

解法:(dij)

进行正向和反向建图。(把问题转化为单源最短路)求由x到其他节点的最短路。分别求两次。之后再for找最大值即可(dis1【i】+dis2【i】)。

总结教训:

函数里的a【】只是一个指针,不能直接sizeof(memset赋值的)

AC(dij)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define fzhead EDGE (int _to, int _v, int _next)
#define fzbody to(_to),v(_v),next(_next)
#define For(i,x,y) for (register int i=(x);i<=(y);i++)
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int>pa;
typedef pair<ll,ll>PA;
const int maxn=1e5+10;
inline int read()
{
    int ans=0;
    char c=getchar();bool neg=false;
    while(c<'0'||c>'9')
    {
        if(c=='-')neg=true;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        ans=ans*10+c-'0';
        c=getchar();
    }
    return (neg)?-ans:ans;
}
void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
struct EDGE
{
    int to,next,v;
    EDGE(){}
    fzhead : fzbody{}
}e1[maxn],e2[maxn];
int n,m,cnt1,k,cnt2;
int vis[maxn],dis1[maxn],head1[maxn],dis2[maxn],head2[maxn];
void add(int bg, int ed, int v,EDGE e[maxn],int &cnt,int head[maxn])
{
    e[++cnt]=EDGE(ed,v,head[bg]);
    head[bg]=cnt;
}
inline void dij(EDGE e[], int dis[],int head[])
{
    memset(dis,0x3f,sizeof(dis1));
    For(i,1,n)vis[i]=0;
    priority_queue<pa>q;
    dis[k]=0;
    q.push(mp(0,k));
    while(!q.empty())
    {
        int u=q.top().se;q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int i=head[u]; i!=-1; i=e[i].next)
        {
            if(dis[e[i].to]>dis[u]+e[i].v)
            {
                dis[e[i].to]=dis[u]+e[i].v;
                q.push(mp(-dis[e[i].to],e[i].to));
            }
        }
    }
}
int main()
{
    memset(head1, -1, sizeof(head1));
    memset(head2,-1,sizeof(head2));
    n=read();m=read();k=read();
    for(int i=1; i<=m; i++)
    {
        int x,y,v;
        x=read(),y=read(),v=read();
        add(x,y,v,e1,cnt1,head1);
        //cout<<e1[cnt1].to<<' '<<e1[cnt1].next<<' '<<e1[cnt1].v<<endl;
        add(y,x,v,e2,cnt2,head2);
        //cout<<e2[cnt2].to<<' '<<e2[cnt2].next<<' '<<e2[cnt2].v<<endl;
       // cout<<endl;
    }
    dij(e1,dis1,head1);
    dij(e2,dis2,head2);
  //  for(int i=1; i<=n; i++)cout<<dis1[i]<<endl;
    int ans=0;
    for(int i=1; i<=n; i++)
    {
        ans=max(dis1[i]+dis2[i],ans);
    }
    write(ans);
    putchar('\n');
    return 0;
}

Invitation Cards(poj1511)

在这里插入图片描述
在这里插入图片描述

Sample Input:

2
2 2
1 2 13
2 1 33
4 6
1 2 10
2 1 60
1 3 20
3 4 10
2 4 5
4 1 50

Sample Output

46
210

题意:

本题要你从1节点出发,把所有志愿者送到各个节点。
之后再把志愿者送回来。求最短路。

思路:

反向建边,分别求两次dij,之后把从1到每个点的dis,加起来即可。

总结教训

  1. 不开longlong见祖宗
  2. 初始化要彻底。

AC(dij)

#include <iostream>
#include <cstring>
#include  <cstdio>
#include <queue>
#define fzhead EDGE (long long  _to, long long  _v, long long  _next)
#define fzbody to(_to), v(_v), next(_next)
#define For(i,x,y) for (register int i=(x);i<=(y);i++)
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int>pa;
typedef pair<ll,ll>PA;
inline ll read()
{
    ll ans=0;
    char ch=getchar();bool neg=false;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')neg=true;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        ans=ans*10+ch-'0';
        ch=getchar();
    }
    return (neg)?-ans:ans;
}
void write(ll x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
const int maxn=1e6+10;
struct EDGE
{
    ll to,next,v;
    EDGE(){}
    fzhead : fzbody{}
}e1[maxn],e2[maxn];
ll cnt1,cnt2,n,m;
ll dis1[maxn],dis2[maxn],vis[maxn],head1[maxn],head2[maxn];
void add(ll bg, ll ed, ll v, EDGE e[],ll head[],ll &cnt)
{
    e[++cnt]=EDGE(ed,v,head[bg]);
    head[bg]=cnt;
}
void dij(EDGE e[],ll head[],ll dis[])
{
    memset(dis,0x3f,sizeof(dis1));
    For(i,1,n)vis[i]=0;
    priority_queue<PA>q;
    dis[1]=0;q.push(mp(0,1));
    while(!q.empty())
    {
        int u=q.top().se;q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(ll i=head[u];i!=-1;i=e[i].next)
        {
            if(dis[e[i].to]>dis[u]+e[i].v)
            {
                dis[e[i].to]=dis[u]+e[i].v;
                q.push(mp(-dis[e[i].to],e[i].to));
            }
        }
    }
}
int main()
{
    int t;
    t=read();
    while(t--)
    {
        cnt1=cnt2=0;
        memset(head1,-1,sizeof(head1));
        memset(head2,-1,sizeof(head2));
        n=read(),m=read();
        For(i,1,m)
        {
            ll x,y,v;
            x=read(),y=read(),v=read();
            add(x,y,v,e1,head1,cnt1);
            add(y,x,v,e2,head2,cnt2);
        }
        dij(e1,head1,dis1);
      //  For(i,1,n)cout<<dis1[i]<<' ';
       // cout<<endl;
        dij(e2,head2,dis2);
        ll ans=0;
        For(i,1,n)ans+=dis1[i]+dis2[i];
        write(ans);
        putchar('\n');
    }
    return 0;
}

Heavy Transportation(poj1797)

(最短路的变式)

在这里插入图片描述
在这里插入图片描述

Sample Input

1
3 3
1 2 3
1 3 4
2 3 5

Sample Output

Scenario #1:
4

题意&&题解:

  1. 由m条边,求出1到n中需要的边最大(最短路的变式)
  2. 本题的dis要改成存1到这个点i的最大边权。
  3. 原本的松弛操作是把大的dis放到队尾,这道题要把大的dis放到队首。
  4. 本题的输出是要 \n 的 233

反思总结:

  1. 对于每个点算边权,要看从v到u(u出队节点),如果dis【v】更小,说明从u到v之前有更大的边权,这时就要入队了。
  2. 优先队列默认大根堆,本题求最大直接入队,(求最小的话,加‘-’,再入队)
  3. 原本的松弛操作 : d[v]= min(d[v], d[u]+w);
  4. 本题的松弛操作 : d[v]= max(d[v] , min(d[u], w);

AC(dij)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define fzhead EDGE(int _to, int _v, int _next)
#define fzbody to(_to) ,v(_v) ,next(_next)
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
#define mp make_pair
#define se second
#define fi first
using namespace std;
typedef long long ll;
typedef pair<int,int>pa;
typedef pair<ll,ll>PA;
const int maxn=1e3+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
inline int read()
{
    int ans=0;
    char ch=getchar();bool neg=false;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')neg=true;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        ans=ans*10+ch-'0';
        ch=getchar();
    }
    return (neg)?-ans:ans;
}
void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
struct EDGE
{
    int to,next,v;
    EDGE(){}
    fzhead : fzbody{}
}e[maxm];
int vis[maxn],dis[maxn],head[maxn];
int cnt,n,m;
void add(int bg, int ed, int v)
{
    e[++cnt]=EDGE(ed,v,head[bg]);
    head[bg]=cnt;
}
void dij(int s)
{
    memset(dis,0,sizeof(dis));//求最大边权,除起点外,其他点初始化为0
    For(i,1,n)vis[i]=0;
    priority_queue<pa>q;
    dis[s]=INF;q.push(mp(dis[s],s));
    while(!q.empty())
    {
        int u=q.top().se;q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int i=head[u]; i!=-1; i=e[i].next)
        {
            int v=e[i].to,w=e[i].v;
            if(dis[v]<min(dis[u],w))
            {
                dis[v]=min(dis[u],w);
                q.push(mp(dis[v],v));//大的在队首
            }
        }
    }
}
int main()
{
    int t,kase=0;
    t=read();
    while(t--)
    {
        memset(head,-1,sizeof(head));
        cnt=0;
        n=read(),m=read();
        For(i,1,m)
        {
            int x=read(),y=read(),v=read();
            add(x,y,v);
            add(y,x,v);
        }
        dij(1);
        printf("Scenario #%d:\n%d\n\n", ++kase, dis[n]);
       // printf("Scenario #%d:\n", ++kase);
        //write(ans);
       // putchar('\n');
       // putchar('\n');
    }
    return 0;
}

Frogger poj2253(最短路变形)

在这里插入图片描述

Sample Input

**2
0 0
3 4

3
17 4
19 4
18 5

0**

Sample Output

Scenario #1
Frog Distance = 5.000
Scenario #2
Frog Distance = 1.414

题意&&题解

有一只青蛙A(1号节点),想跳到青蛙B的石头上(2号节点),但不是直接跳过去,湖中间还有其他石头。
题目要求你跳到b上,找到最短路中的最大的边权(所以这道题的松弛操作时的存路径改为存最长边)

反思总结

  1. 这道题先算边权,而要用坐标公式,即要用double。
  2. memset的时候我忘记了double不能直接0x3f,一直debug
    233

AC(dij)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#define fzhead EDGE(int _to, double _v, int _next)
#define fzbody to(_to), v(_v), next(_next)
#define For(i,x,y) for(register int i=(x);i<=(y);i++)
#define mp make_pair
#define fi first
#define se second
using namespace std;
inline int read()
{
    int ans=0;
    char ch=getchar();
    bool neg=false;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')neg=false;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        ans=ans*10+ch-'0';
        ch=getchar();
    }
    return (neg)?-ans:ans;
}
double ca(int x, int y, int x1, int y1)
{
    int m=(x-x1)*(x-x1)+(y-y1)*(y-y1);
    return sqrt(double(m));
}
typedef long long ll;
typedef pair<double,int>pa;
const int maxm=1e6+1e3;
const int INF=0x3f3f3f3f3f;
const int maxn=2e2+10;
struct EDGE
{
    int to,next;
    double v;
    EDGE() {}
fzhead:
    fzbody{}
} e[maxm];
double dis[maxn];
int vis[maxn],head[maxn],x[maxn],y[maxn];
int n,m,cnt;
void add(int bg, int ed, double v)
{
    e[++cnt]=EDGE(ed,v,head[bg]);
    head[bg]=cnt;
}
void dij(int s)
{
    For(i,1,n)vis[i]=0;
    priority_queue<pa>q;
    dis[1]=0;
    q.push(mp(dis[s],s));
    while(!q.empty())
    {
        int u=q.top().se;
        q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int i=head[u]; i!=-1; i=e[i].next)
        {
            int v=e[i].to;
            double w=e[i].v;
            //cout<<dis[v]<<' '<<v<<endl;
            if(dis[v]>max(dis[u],w))
            {
                dis[v]=max(dis[u],w);
                //cout<<dis[v]<<' '<<v<<endl;
                q.push(mp(-dis[v],v));
            }
        }
    }
}
int main()
{
    int kase=0;
    while(scanf("%d", &n)&&n)
    {
        For(i,1,n)dis[i]=INF;///
        cnt=0;
        memset(head,-1,sizeof(head));
        for(int i=1; i<=n; i++)
            x[i]=read(),y[i]=read();
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                if(i!=j)
                {
                    double d=ca(x[i],y[i],x[j],y[j]);
                    add(i,j,d);
                }
            }
        }
        // cout<<dis[2]<<endl;
        //for(int i=1; i<=n; i++)cout<<dis[i]<<' ';
        // cout<<endl<<endl;
        dij(1);
       // for(int i=1; i<=n; i++)cout<<dis[i]<<' ';
       // cout<<endl;
        printf("Scenario #%d\nFrog Distance = %.3lf\n\n",++kase,dis[2]);
    }
    return 0;
}

The Shortest Path in NyaGraph(hdu4725)

在这里插入图片描述
在这里插入图片描述

Sample Input

**2
3 3 3
1 3 2
1 2 1
2 3 1
1 3 3

3 3 3
1 3 2
1 2 2
2 3 2
1 3 4**

Sample Output

Case #1: 2
Case #2: 3

题意&&思路

本题是求最短路,可是本题有了一个条件:就是有层次。
而直接把dujust层的点连边的话,复杂度不允许。

tip:本题可以建立一个层次节点

总共边数为7n=5n(建立层次节点为本层1n+2n+2n)+2n(m条边)

AC(dij)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define fi first
#define se second
#define mp make_pair
#define mst(x,a) memset(x,a,sizeof(x))
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
#define fzhead EDGE(int _to, int _v, int _next)
#define fzbody to(_to), v(_v), next(_next)
using namespace std;
typedef long long ll;
typedef pair<int,int>pa;
typedef pair<ll,ll>PA;
const int maxm=8e5+10;
const ll INF= 0x3f3f3f3f3f3f3f3f;
const int maxn=2e5+10;
struct EDGE
{
    int to,next;
    ll v;
    EDGE(){}
    fzhead:fzbody{}
}e[maxm];
int vis[maxn],head[maxn];
ll dis[maxn],c;
int cnt,n,m;
void add(int bg, int ed, ll v)
{
    e[++cnt]=EDGE(ed, v, head[bg]);
    head[bg]=cnt;
}
void dij(int s)
{
    For(i,1,2*n)vis[i]=0;
    mst(dis,0x3f);
    priority_queue<PA>q;
    dis[s]=0;q.push(mp(dis[s],s));
    while(!q.empty())
    {
        int u=q.top().se;q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int i=head[u]; i!=-1; i=e[i].next)
        {
            int v=e[i].to, w=e[i].v;
            if(dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                q.push(mp(-dis[v],v));
            }
        }
    }
}
int main()
{
    int t,kase=0;
    scanf("%d", &t);
    while(t--)
    {
        cnt=0;
        mst(head,-1);
        scanf("%d%d%lld",&n,&m,&c);
        int cur;
        For(i,1,n)
        {
            scanf("%d",&cur);
            add(n+cur,i,0);//建立层次节点,这个点到本层的距离为0
            if(cur+1<=n)add(n+cur+1,i,c),add(i,n+cur+1,c);//这个点到相邻层的距离为c
            if(cur-1>=1)add(n+cur-1,i,c),add(i,n+cur-1,c);
        }
        ll v;
        For(i,1,m)
        {
            int x,y;
            scanf("%d%d%lld",&x,&y,&v);
            add(x,y,v);
            add(y,x,v);
        }
        dij(1);
      //  For(i,1,n)cout<<dis[i]<<' ';
      //  cout<<endl;
        printf("Case #%d: ", ++kase);
        if(dis[n]==INF)
            printf("-1\n");
        else
            printf("%lld\n", dis[n]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值