L2-001 城市间紧急救援

总体上,用个Dijkstra算法
稍加修改就行
经测试,救援经过的城市不会超过50;
相同长度的路径数不会超10;
如果结构直接设个500的数组会占太多内存而崩掉

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define INF 65535
struct zlh{
 int vis;//是否已经找出 
 int u;//存路程 
 int g;//存一共有几条路径 
 int ru[10][50];//ru 这个二维数组用来存路径 
 int p[10];//存若干条路径的长度 
};
int jc[500][500]={0};
int main(){
 struct zlh yu[500]={}; 
 for(int i=0;i<=499;i++)
  yu[i].g=1; 
 int a,b,m1,n1,y=0,ui[1000]={};
 scanf("%d%d%d%d",&a,&b,&m1,&n1); 
 for(int i=0;i<a;i++)
  scanf("%d",&ui[i]);
 ui[999]=ui[0];
 ui[0]=ui[m1];
 ui[m1]=ui[999];
 for(int i=1;i<=b;i++){
  int u,m,r;
  scanf("%d%d%d",&u,&m,&r);
  if(!u) u=m1;//先写了以0为起点的算法,后来发现看错了 不想改,就加了个补丁. 
  else if(u==m1) u=0;
  if(!m) m=m1;
  else if(m==m1) m=0;
  jc[u][m]=r;
  jc[m][u]=r;
 }
 for(int i=1;i<a;i++)
  for(int t=1;t<a;t++)
   jc[i][t]=!jc[i][t]||i==t?INF:jc[i][t];          
 for(int i=1;i<a;i++){
  yu[i].u=!jc[0][i]?INF:jc[0][i];
 }   
 while(++y<a){
  int min=INF,k=0;
  for(int i=1;i<a;i++){
   if(!yu[i].vis&&yu[i].u<min){
    min=yu[i].u;
    k=i;
   }    
  }    
  for(int i=1;i<a;i++){
   if(yu[i].u>jc[k][i]+min){
    yu[i].g=yu[k].g;
    yu[i].u=jc[k][i]+min;
    for(int q=1;q<=yu[k].g;q++){
     yu[i].p[q]=yu[k].p[q];
     for(int t=0;t<=yu[k].p[q];t++)
      yu[i].ru[q][t]=yu[k].ru[q][t];
     yu[i].ru[q][++yu[i].p[q]]=k;
    }    
   }
   else if(yu[i].u==jc[k][i]+min){
    for(int q=1;q<=yu[k].g;q++){
     yu[i].p[++yu[i].g]=yu[k].p[q];
     for(int t=0;t<=yu[k].p[q];t++)
      yu[i].ru[yu[i].g][t]=yu[k].ru[q][t];
     yu[i].ru[yu[i].g][++yu[i].p[yu[i].g]]=k;     
    }
   }
  }
  yu[k].vis=1;
 }
 if(!n1) n1=m1;
 printf("%d",yu[n1].g);
 int se=0,sr=0;
 for(int i=1;i<=yu[n1].g;i++){
  int gh=0;
  for(int t=0;t<=yu[n1].p[i];t++){
    gh+=ui[yu[n1].ru[i][t]];   
  }  
  gh+=ui[n1];
  
  if(gh>se){
   sr=i;
   se=gh;
  } 
 }
 printf(" %d\n",se);
 for(int i=0;i<=yu[n1].p[sr];i++){
  if(yu[n1].ru[sr][i]==0) printf("%d ",m1);
  else if(yu[n1].ru[sr][i]==m1) printf("%d ",0);
  else printf("%d ",yu[n1].ru[sr][i]);
 }
 printf("%d\n",n1==m1?0:n1);  
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值