最短路径问题 eg.城市平乱

来源:互联网 发布:jq push 二维数组 编辑:程序博客网 时间:2024/04/29 04:20

南阳oj里的一道题:115


刚开始的弗洛伊德算法(超时的):

#include<stdio.h>int dist[101][1001];int main(){int T,i;scanf("%d",&T);while(T--){int N,M,P,Q;int ni[101];scanf("%d%d%d%d",&N,&M,&P,&Q);for(i=0;i<N;i++)scanf("%d",&ni[i]);for(i=1;i<=M;i++)for(int j=1;j<=M;j++)dist[i][j]=101;while(P--){int a,b,t;scanf("%d%d%d",&a,&b,&t);dist[a][b]=t;}for(int k=1;k<=M;k++)for(i=1;i<=M;i++)for(int j=i+1;j<=M;j++)if(dist[i][k]+dist[k][j]<dist[i][j]){dist[i][j]=dist[i][k]+dist[k][j];}int min=dist[ni[0]][Q];for(i=1;i<N;i++){if(dist[ni[i]][Q]<min)min=dist[ni[i]][Q];}printf("%d\n",min);}return 0;} 


看了别人总结的迪杰斯特拉算法:

http://blog.csdn.net/whjkm/article/details/38459733

模板如下:

<pre name="code" class="cpp">void dijkstra(int start)//从一个给定的点开始   low[i]为start到i的路径长{    int i,j,min,pos;    memset(visit,0,sizeof(visit));//初始化visit数组    for(i=1;i<=m;i++)    {        low[i]=map[start][i];    }    low[start]=0;//自身的权值为0    visit[start]=1;    for(i=1;i<m;i++)    {        min=Max;        pos=0;        for(j=1;j<=m;j++)        {            if(!visit[j] && min>low[j])//比较最小值,更新min值            {                min=low[j];                pos=j;            }        }        visit[pos]=1;        for(j=1;j<=m;j++)        {            if(low[j]>min+map[pos][j])//更新low数组                low[j]=min+map[pos][j];        }    }}


通过代码如下:

#include<stdio.h>#include<string.h>#define inf 0x3f3f3f3f#define Vex 1001int map[Vex][Vex];int low[Vex];int M;int visit[Vex];void dijstral(int start){int i,j,min,pos;for(i=1;i<=M;i++)low[i]=map[start][i];memset(visit,0,sizeof(visit));low[start]=0;//自身权值为0 visit[start]=1; for(i=1;i<=M;i++){min=inf;pos=0;for(j=1;j<=M;j++){if(!visit[j]&&low[j]<min){min=low[j];pos=j;}}visit[pos]=1;for(j=1;j<=M;j++){if(min+map[pos][j]<low[j]){low[j]=min+map[pos][j];}}}}int main(){int T;int N,P,Q;int num[101];scanf("%d",&T);while(T--){memset(map,inf,sizeof(map));scanf("%d%d%d%d",&N,&M,&P,&Q);int i;for(i=0;i<N;i++)scanf("%d",&num[i]);while(P--){int a,b,t;scanf("%d%d%d",&a,&b,&t);if(map[a][b]>t)              map[a][b]=map[b][a]=t; }dijstral(Q);int temp=inf;for(i=0;i<N;i++)if(low[num[i]]<temp)temp=low[num[i]];printf("%d\n",temp);}return 0;}



看解题报告的一次迪杰斯特拉算法:

自己多加一个超级源点,把起点集合连接到超级源点上,然后将起点与超级源点的集合的路径长度设为0,这样就称为一个n+1个点的单源最短路算法。。。。。此时,只需要一次Dijkstra就可以求出这个最短长度。
#include<stdio.h>#include<string.h>#define inf 0x3f3f3f3f#define Vex 1001int map[Vex][Vex];int low[Vex];int M;int visit[Vex];void dijstral(){int i,j,min,pos;for(i=0;i<=M;i++)low[i]=map[0][i];memset(visit,0,sizeof(visit));low[0]=0;visit[0]=1; for(i=0;i<=M;i++){min=inf;pos=0;for(j=0;j<=M;j++){if(!visit[j]&&low[j]<min){min=low[j];pos=j;}}visit[pos]=1;for(j=0;j<=M;j++){if(min+map[pos][j]<low[j]){low[j]=min+map[pos][j];}}}}int main(){int T,a,b,t,num,N,P,Q,i;scanf("%d",&T);for(i=0;i<T;i++){memset(map,inf,sizeof(map));scanf("%d%d%d%d",&N,&M,&P,&Q);int i;for(i=0;i<N;i++){scanf("%d",&num);map[0][num]=0; }for(num=0;num<P;num++){scanf("%d%d%d",&a,&b,&t);if(map[a][b]>t)              map[a][b]=map[b][a]=t;}dijstral();printf("%d\n",low[Q]);}return 0;}




1 0
原创粉丝点击