洛谷题单图论2-2最短路练习

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

一、P1119 灾后重建

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 210;
int n, m, Q;
ll dist[N][N];
int a[N];

void update(int x){
    
    for(int i = 0; i < n; i ++)
        for(int j = 0; j < n; j ++)
            if(dist[i][j] > dist[i][x] + dist[x][j])
                dist[i][j] = dist[i][x] + dist[x][j];

    return ;
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i = 0;  i< n; i ++) scanf("%d",&a[i]);

    for(int i = 0; i < n; i ++)
        for(int j = 0; j < n; j ++){
            if(i == j) dist[i][j] = 0;
            else dist[i][j] = 1e9;
        }
            

    while(m--){
        int x, y, l;
        scanf("%d%d%d",&x,&y,&l);
        dist[x][y] = dist[y][x] = l;
    }

    scanf("%d",&Q);
    
    int cnt = 0;
    while(Q--){
        int x, y, t;
        scanf("%d%d%d",&x,&y,&t);
        while(a[cnt] <= t && cnt < n){
            update(cnt);
            cnt ++;
        }
        if(a[x] > t || a[y] > t) puts("-1");
        else {
            if(dist[x][y] == 1e9) puts("-1");
            else printf("%d\n",dist[x][y]);
        }
    }
    
    return 0;
}
 

二、P1119 灾后重建

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5 +10;
typedef pair<int,int>PII;
int n, m, s;
int h[N],e[N],ne[N],w[N],idx;
void add(int x,int y,int z){//向前星存图
    e[++idx] = y;
    w[idx] = z;
    ne[idx] = h[x];
    h[x] = idx;
}

ll dist[100010];
bool st[100010];
priority_queue<PII,vector<PII>,greater<PII> >q;//优先队列
void dij(int x){
    fill(dist,dist+100010,2147483647);//初始化赋值
    
    dist[x] = 0;
    q.push(make_pair(0,x));//把距离和点放入队列,把距离放在前面以便于自动排序使得对头是最短距离

    while(q.size()){
        int ver = q.top().second,distance = q.top().first;
        q.pop();
        if(st[ver]) continue;
        st[ver] = 1;

        for(int i = h[ver]; i; i = ne[i]){
            int j = e[i];
            if(dist[j] > distance + w[i]){

                dist[j] = distance + w[i];
                q.push(make_pair(dist[j],j));
            }
        }

    }
}

int main(){
    scanf("%d%d%d",&n,&m,&s);
    while(m--){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    
    dij(s);
    for(int i = 1; i <= n; i ++){
        printf("%lld ",dist[i]);
    }

    return 0;
}
 

三、P1629 邮递员送信

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
const int N = 3e5 +10;
vector<int>v;
map<int,int>mp;
int n, m;

int h[3000],e[N],ne[N],w[N],idx;
void add(int x,int y,int z){
    e[++idx] = y;
    w[idx] = z;
    ne[idx] = h[x];
    h[x] = idx;
}

ll dist[N];
bool st[N];

void dij(int x){
    priority_queue<PII,vector<PII>,greater<PII> >q;
    memset(dist,0x3f,sizeof dist);
    dist[x] = 0;
    q.push(make_pair(0,x));

    while(q.size()){
        int ver = q.top().second,distance = q.top().first;
        q.pop();
        if(st[ver]) continue;
        st[ver] = 1;

        for(int i = h[ver]; i; i = ne[i]){
            int j = e[i];
            if(dist[j] > distance + w[i]){

                dist[j] = distance + w[i];
                q.push(make_pair(dist[j],j));
            }
        }

    }
}


ll ans;

int main(){
    scanf("%d%d",&n,&m);
    while(m--){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        add(v+n,u+n,w);
    }

    ans = 0;
    dij(1);
    for(int i = 2;  i<= n; i ++) ans += dist[i];
    dij(1+n);
    for(int i = 2 + n;  i <= n << 1; i ++) ans += dist[i];
    
    printf("%ld\n",ans);
    return 0;
}
 

四、P4779 【模板】单源最短路径(标准版)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5 +10;
typedef pair<int,int>PII;
int n, m, s;
int h[N],e[N],ne[N],w[N],idx;
void add(int x,int y,int z){//向前星存图
    e[++idx] = y;
    w[idx] = z;
    ne[idx] = h[x];
    h[x] = idx;
}

ll dist[100010];
bool st[100010];
priority_queue<PII,vector<PII>,greater<PII> >q;//优先队列
void dij(int x){
    fill(dist,dist+100010,2147483647);//初始化赋值
    
    dist[x] = 0;
    q.push(make_pair(0,x));//把距离和点放入队列,把距离放在前面以便于自动排序使得对头是最短距离

    while(q.size()){
        int ver = q.top().second,distance = q.top().first;
        q.pop();
        if(st[ver]) continue;
        st[ver] = 1;

        for(int i = h[ver]; i; i = ne[i]){
            int j = e[i];
            if(dist[j] > distance + w[i]){

                dist[j] = distance + w[i];
                q.push(make_pair(dist[j],j));
            }
        }

    }
}

int main(){
    scanf("%d%d%d",&n,&m,&s);
    while(m--){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    
    dij(s);
    for(int i = 1; i <= n; i ++){
        printf("%lld ",dist[i]);
    }

    return 0;
}
 

五、P1144 最短路计数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5 +10,mod = 100003;
typedef pair<int,int>PII;
int n, m, s;
int h[1000005],e[4000005],ne[4000005],idx;
void add(int x,int y){//向前星存图
    e[++idx] = y;
    ne[idx] = h[x];
    h[x] = idx;
}

ll dist[1000010],ans[1000010];
bool st[1000010];
priority_queue<PII>q;//优先队列
void dij(){
    memset(dist,0x3f,sizeof dist);//初始化赋值
    
    dist[1] = 0;
    q.push(make_pair(0,1));//把距离和点放入队列,把距离放在前面以便于自动排序使得对头是最短距离
    ans[1] = 1;
    while(q.size()){
        int ver = q.top().second;
        q.pop();
        if(st[ver]) continue;
        st[ver] = 1;

        for(int i = h[ver]; i; i = ne[i]){
            int j = e[i];
            if(dist[j] > dist[ver] + 1){

                dist[j] = dist[ver] + 1;
                ans[j] = ans[ver];
                q.push(make_pair(-dist[j],j));
            }else if(dist[j] == dist[ver] + 1){
                ans[j] += ans[ver];
                ans[j] %= mod;
            }
        }

    }
}

int main(){
    scanf("%d%d",&n,&m);
    while(m--){
        // cout <<"*************"<<endl;
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }

    
    dij();
    
    for(int i = 1; i <= n; i ++){
        printf("%lld\n",ans[i]);
    }

    return 0;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值