• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • YouClaw
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

yongchaoD

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

HDU2680 (超级源点多起点最短路)

题目:https://acm.hdu.edu.cn/showproblem.php?pid=2680
题意:多个起点到终点的最短路的最短距离
最开始是用反向建图,跑一个dij,然后枚举找到多个起点的最短距离,时间复杂度为:一个dij+枚举n个起点。
更优化的能用超级源点,时间复杂度能优化到一个dij。
超级源点就是创建一个点0点,然后从0点建边到所有起点,权值为0,然后将0点作为新的起点,跑一个dij。因为0作为新起点,下一步一定就是走原来的各个起点,最后dis[终点]就是0点到终点的最短路径,但是0点到各个起点的权值设为的0,相当于并没有算0点到其中某一个起点(dis[终点]肯定只是经过了其中一个起点)的权值。
//

点击查看代码
//超级源点(时间复杂度为一个最短路。反向建图,是一个最短路+枚举n)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e4+9;
int n,m,s,Min=N;
vector<pair<int,int>>G[N];//first:存值
vector<int>dis(N,N),vis(N,0);

void dij(int st){//st:起点
    priority_queue<pair<int,int>>q;//q.first:存起点到second点当前要用的最短路程
    q.push({0,st});
    dis[st]=0;

    while(!q.empty()){
        int u=q.top().second;
        q.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(auto[x,y]:G[u]){//u--->y
            if(dis[y]>dis[u]+x){//x在存图中就是u到y的距离
                dis[y]=dis[u]+x;
                q.push({-dis[y],y});
            }
        }
    }
}

void solve(){
    for(int i=0;i<N;i++){
        G[i].clear();
        dis[i]=N;
        vis[i]=0;
    }

    for(int i=1;i<=m;i++){
        int u,v,len;
        scanf("%lld %lld %lld", &u, &v, &len);
        G[u].push_back({len,v});
    }


    int q,st;
    scanf("%lld", &q);
      while(q--){//多个起点
          scanf("%lld",&st);
          G[0].push_back({0,st});//超级源点到所有起点的距离=0
      }
    dij(0);

    if(dis[s]==N) printf("-1\n");
    else printf("%ld\n",dis[s]);
}

signed main()
{
    while(~scanf("%d%d%d",&n,&m,&s)){
        solve();
    }
    return 0;
}

posted on 2024-07-06 16:00  yongchaoD  阅读(26)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3