luogu P2683 小岛

裸的最短路模板,数据范围小,完全可以直接在每次询问的时候跑一遍最短路就行,如果担心时间的话,可以用堆优化的dijkstra,完全可以过,堆可以手打,但作为stl党, 我们可是有黑科技的。优先队列相当于一个大根堆,你可以使用stl的pair使他成为小根堆,也可以通过运算符装载将其重载为小根堆。

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
struct node{//小根堆重载
    int now,x;//now代表点的位置,x代表距离
    bool operator <(const node &tmp) const
    {
        return x>=tmp.x;
    }
}cur;
int head[110],to[10010],nxt[10010],v[10010],num,dis[10010],e,n,m,x,y,k;
bool vis[110];
const int inf=2147483647; 
void add(int x,int y,int z)//前向星建图,因为是双向边,所以存两条边
{
    to[++num]=y;
    v[num]=z;
    nxt[num]=head[x];
    head[x]=num;
    to[++num]=x;
    v[num]=z;
    nxt[num]=head[y];
    head[y]=num;
}
void dij(int s)
{
    priority_queue<node>q;
    fill(dis+1,dis+n+1,inf);//初始化,一定要初始化,不然它会与上次查询有冲突。
    fill(vis+1,vis+n+1,0);
    dis[s]=0;
    q.push((node){
        s,dis[s]
    });
    while(!q.empty())
    {
        cur=q.top();
        q.pop();
        if(vis[cur.now]) continue;
        vis[cur.now]=1;
        for(int i=head[cur.now];i;i=nxt[i])
        {
            if(dis[to[i]]>dis[cur.now]+v[i])//路径压缩
            {
                dis[to[i]]=dis[cur.now]+v[i];
                q.push((node){
                    to[i],dis[to[i]]
                });
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&k);
        if(k==0)
        {
            scanf("%d%d",&x,&y);
            dij(x);//遍历最短路
            printf("%d\n",dis[y]==inf?-1:dis[y]);
        }
        else 
        {
            scanf("%d%d%d",&x,&y,&e);
            add(x,y,e);//加边
        }
    }
    return 0;
}   

猜你喜欢

转载自blog.csdn.net/weixin_43795131/article/details/84894968