• 单源最短路的建图


    目录

    1.热浪

    2.信使

    3.香甜的黄油

    4.最小花费

    5.最优乘车

    6.昂贵的聘礼


    1.热浪

    信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

    很裸的单源最短路问题,n=2500,可以用dijksta或者spfa都能过,下面展示spfa的做法

    1. #include
    2. using namespace std;
    3. const int N=2510,M=6200*2+10;
    4. int h[N],e[M],ne[M],w[M],idx;
    5. int dist[N];
    6. bool st[N];
    7. int S,E;
    8. void add(int a,int b,int c)
    9. {
    10. w[idx]=c,e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    11. }
    12. int spfa()
    13. {
    14. memset(dist,0x3f,sizeof dist);
    15. dist[S]=0;
    16. queue<int> q;
    17. q.push(S);
    18. st[S]=true;
    19. while(q.size())
    20. {
    21. int t=q.front();
    22. q.pop();
    23. st[t]=false;
    24. for(int i=h[t];~i;i=ne[i])
    25. {
    26. int j=e[i];
    27. if(dist[j]>dist[t]+w[i])
    28. {
    29. dist[j]=dist[t]+w[i];
    30. if(!st[j])
    31. {
    32. q.push(j);
    33. st[j]=true;
    34. }
    35. }
    36. }
    37. }
    38. return dist[E];
    39. }
    40. int main()
    41. {
    42. int T,m;
    43. cin>>T>>m>>S>>E;
    44. memset(h,-1,sizeof h);
    45. for(int i=0;i
    46. {
    47. int a,b,c;
    48. cin>>a>>b>>c;
    49. add(a,b,c),add(b,a,c);
    50. }
    51. cout<<spfa()<
    52. return 0;
    53. }

    2.信使

    信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

    由于数据较小可以用Floyd算法求两两之间的最短路,然后后面更新一遍一号点到每一个点的最小距离即可

    1. #include
    2. using namespace std;
    3. const int N=110;
    4. int dist[N][N];
    5. int n,m;
    6. int flyd()
    7. {
    8. for(int k=1;k<=n;k++)
    9. for(int i=1;i<=n;i++)
    10. for(int j=1;j<=n;j++)
    11. dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
    12. int ans=0;
    13. for(int i=2;i<=n;i++) ans=max(dist[1][i],ans);
    14. return ans;
    15. }
    16. int main()
    17. {
    18. cin>>n>>m;
    19. memset(dist,0x3f,sizeof dist);
    20. for(int i=0;i
    21. {
    22. int a,b,c;
    23. cin>>a>>b>>c;
    24. dist[a][b]=dist[b][a]=min(dist[a][b],c);
    25. }
    26. int t=flyd();
    27. if(t==0x3f3f3f3f) puts("-1");
    28. else cout<
    29. return 0;
    30. }

    3.香甜的黄油

    1127. 香甜的黄油 - AcWing题库

    枚举每一个农场,然后算一下总距离,然后更新每一个农场的最小值,用spfa求最小距离

    1. #include
    2. using namespace std;
    3. const int N=810,M=3000;
    4. int h[N],e[M],ne[M],w[M],idx;
    5. int id[N],dist[N];
    6. int n,p,c;
    7. bool st[N];
    8. void add(int a,int b,int c)
    9. {
    10. w[idx]=c,e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    11. }
    12. int spfa(int s)
    13. {
    14. memset(dist,0x3f,sizeof dist);
    15. memset(st,0,sizeof st);
    16. queue<int> q;
    17. q.push(s);
    18. dist[s]=0;
    19. st[s]=true;
    20. while(q.size())
    21. {
    22. int t=q.front();
    23. q.pop();
    24. st[t]=false;
    25. for(int i=h[t];~i;i=ne[i])
    26. {
    27. int j=e[i];
    28. if(dist[j]>dist[t]+w[i])
    29. {
    30. dist[j]=dist[t]+w[i];
    31. if(!st[j])
    32. {
    33. q.push(j);
    34. st[j]=true;
    35. }
    36. }
    37. }
    38. }
    39. int ans=0;
    40. for(int i=1;i<=n;i++)
    41. {
    42. int j=id[i];
    43. if(dist[j]==0x3f3f3f3f) return 0x3f3f3f3f;
    44. ans+=dist[j];
    45. }
    46. return ans;
    47. }
    48. int main()
    49. {
    50. cin>>n>>p>>c;
    51. memset(h,-1,sizeof h);
    52. for(int i=1;i<=n;i++) cin>>id[i];
    53. for(int i=0;i
    54. {
    55. int a,b,c;
    56. cin>>a>>b>>c;
    57. add(a,b,c),add(b,a,c);
    58. }
    59. int ans=0x3f3f3f3f;
    60. for(int i=1;i<=p;i++) ans=min(ans,spfa(i));
    61. cout<
    62. return 0;
    63. }

    4.最小花费

    信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

    算乘法的最短路,也就是把加法改成乘法即可,在求乘的最大值,dist初始化为0就行,用spfa可以过

    1. #include
    2. using namespace std;
    3. const int N=2010,M=2e5+10;
    4. int h[N],e[M],ne[M],idx;
    5. double w[M];
    6. double dist[N];
    7. int n,m;
    8. int A,B;
    9. bool st[N];
    10. void add(int a,int b,double c)
    11. {
    12. w[idx]=c,e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    13. }
    14. double spfa()
    15. {
    16. queue<int> q;
    17. q.push(A);
    18. dist[A]=1;
    19. st[A]=true;
    20. while(q.size())
    21. {
    22. int t=q.front();
    23. q.pop();
    24. st[t]=false;
    25. for(int i=h[t];~i;i=ne[i])
    26. {
    27. int j=e[i];
    28. if(dist[j]
    29. {
    30. dist[j]=dist[t]*w[i];
    31. if(!st[j])
    32. {
    33. q.push(j);
    34. st[j]=true;
    35. }
    36. }
    37. }
    38. }
    39. return dist[B];
    40. }
    41. int main()
    42. {
    43. cin>>n>>m;
    44. memset(h,-1,sizeof h);
    45. for(int i=0;i
    46. {
    47. int a,b;
    48. double c;
    49. cin>>a>>b>>c;
    50. c=(100-c)/100;
    51. add(a,b,c),add(b,a,c);
    52. }
    53. cin>>A>>B;
    54. double ans=100.0/spfa();
    55. printf("%.8lf",ans);
    56. return 0;
    57. }

    5.最优乘车

    920. 最优乘车 - AcWing题库

    1. #include
    2. using namespace std;
    3. const int N=510;
    4. int stop[N];
    5. int dist[N];
    6. bool g[N][N];
    7. int m,n;
    8. int q[N];
    9. int bfs()//用bfs求最短路,因为边权只有0 1.0表示不能乘坐的到,1表示能乘坐的到
    10. {
    11. memset(dist,0x3f,sizeof dist);
    12. dist[1]=0;
    13. q[0]=1;
    14. int hh=0,tt=0;
    15. while(hh<=tt)
    16. {
    17. int t=q[hh++];
    18. for(int i=1;i<=n;i++)
    19. if(g[t][i]&&dist[i]>dist[t]+1)
    20. {
    21. dist[i]=dist[t]+1;
    22. q[++tt]=i;
    23. }
    24. }
    25. return dist[n];
    26. }
    27. int main()
    28. {
    29. cin>>m>>n;
    30. string line;
    31. getline(cin,line);
    32. while(m--)
    33. {
    34. getline(cin,line);
    35. stringstream ssin(line);
    36. int cnt=0,p;
    37. while(ssin>>p) stop[cnt++]=p;
    38. //将每个站点都连起来,说明有一条路能够通往
    39. for(int i=0;i
    40. for(int j=i+1;j
    41. g[stop[i]][stop[j]]=true;
    42. }
    43. int t=bfs();
    44. if(t==0x3f3f3f3f) puts("NO");
    45. else cout<<bfs()-1<
    46. return 0;
    47. }

    6.昂贵的聘礼

    903. 昂贵的聘礼 - AcWing题库

    把0当作虚拟起点,假如是直接买的话就与0连条边,假如可以由其他物品替换的话加换的那个物品连被换的物品一条边

    等级制度就枚举一个区间内的等级制度即可。然后求最小值

    1. #include
    2. using namespace std;
    3. const int N=110;
    4. int m,n;
    5. int w[N][N],level[N];
    6. bool st[N];
    7. int dist[N];
    8. int dijkstra(int down,int up)//一个是最小等级,一个是最大等级
    9. {
    10. memset(dist,0x3f,sizeof dist);
    11. memset(st,0,sizeof st);
    12. dist[0]=0;
    13. for(int i=1;i<=n;i++)
    14. {
    15. int t=-1;
    16. for(int j=0;j<=n;j++)
    17. if(!st[j]&&(t==-1||dist[j]
    18. t=j;
    19. if(st[t]) continue;
    20. st[t]=true;
    21. for(int j=1;j<=n;j++)
    22. if(level[j]>=down&&level[j]<=up)//等级得在这个范围
    23. dist[j]=min(dist[j],dist[t]+w[t][j]);
    24. }
    25. return dist[1];//返回购买第一个物品的最小值
    26. }
    27. int main()
    28. {
    29. cin>>m>>n;
    30. memset(w,0x3f,sizeof w);
    31. for(int i=1;i<=n;i++) w[i][i]=0;
    32. for(int i=1;i<=n;i++)
    33. {
    34. int p,cnt;
    35. cin>>p>>level[i]>>cnt;
    36. w[0][i]=min(w[0][i],p);//从虚拟原点连一条边到物品i
    37. while(cnt--)//替代物
    38. {
    39. int id,cost;
    40. cin>>id>>cost;
    41. w[id][i]=min(w[id][i],cost);//从替代物连一条边到该物品
    42. }
    43. }
    44. int res=0x3f3f3f3f;
    45. for(int i=level[1]-m;i<=level[1];i++)//最小枚举level[1]-m,最大枚举level[1],因为要覆盖level[1]且长度为m
    46. res=min(res,dijkstra(i,i+m));
    47. cout<
    48. return 0;
    49. }

  • 相关阅读:
    28道Webpack面试题及答案
    【Java】集合 之 Java集合简介
    Java中的ThreadPoolExecutor
    DAY12-深度学习100例-卷积神经网络(CNN)识别验证码
    【C++】C++ 语言对 C 语言的加强 ① ( 实用性增强 - 变量任意位置定义 | register 关键字增强 - 自动进行寄存器优化 )
    FrameWork之旅 -- 源代码主要目录结构
    哪些意想不到的空指针异常
    Java计算机毕业设计大学生社团管理系统源码+系统+数据库+lw文档
    jupyter notebook kernel安装+自动补全
    Java代码中如何向一个HashMap中添加元素呢?
  • 原文地址:https://blog.csdn.net/m0_63729880/article/details/125879365